├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .eslintrc.prod.json
├── .github
├── ISSUE_TEMPLATE
│ └── bug-report.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── browser-tests.yml
│ └── build.yml
├── .gitignore
├── .node-version
├── .npmrc
├── .stylelintrc
├── .travis.yml
├── LICENSE
├── README.md
├── docs
├── _banner.scss
├── _config.js
├── _darkButtons.scss
├── _data
│ ├── icons.json5
│ ├── nav.json5
│ ├── polyfilled-apis.json5
│ └── positions.json5
├── _example.scss
├── _layout.scss
├── _nunjucks
│ ├── code.tag.js
│ └── toc.filter.js
├── _positions.js
├── _shame.scss
├── _templates
│ ├── _utils.njk
│ ├── application.njk
│ ├── component.njk
│ ├── element.njk
│ ├── guide.njk
│ ├── no-frame.njk
│ ├── partials
│ │ ├── app_nav.njk
│ │ ├── lorem-nav.njk
│ │ ├── min-version.njk
│ │ └── see-also.njk
│ ├── props
│ │ ├── Positionable
│ │ │ ├── optimumPosition.njk
│ │ │ ├── relativeElement.njk
│ │ │ └── relativeTo.njk
│ │ └── Revealable
│ │ │ └── open.njk
│ └── test.njk
├── _test-content.scss
├── _toc.scss
├── _util.js
├── components
│ ├── _index.scss
│ ├── accordion
│ │ ├── accordion-demo.js
│ │ ├── index.html
│ │ └── test.html
│ ├── alert
│ │ ├── alert-demo.js
│ │ ├── index.html
│ │ └── test.html
│ ├── badge
│ │ ├── index.html
│ │ └── test.html
│ ├── beacon
│ │ ├── beacon-demo.js
│ │ └── index.html
│ ├── box
│ │ ├── _index.scss
│ │ ├── box-demo.js
│ │ ├── index.html
│ │ └── test.html
│ ├── breadcrumb
│ │ └── index.html
│ ├── button
│ │ ├── _spec.scss
│ │ ├── button-demo.js
│ │ ├── index.html
│ │ └── test.html
│ ├── checkbox
│ │ ├── _spec.scss
│ │ ├── checkbox-demo.js
│ │ ├── index.html
│ │ └── test.html
│ ├── choice-tile
│ │ ├── _spec.scss
│ │ ├── choice-tile-demo.js
│ │ ├── index.html
│ │ └── test.html
│ ├── drawer
│ │ ├── _spec.scss
│ │ ├── drawer-demo.js
│ │ ├── index.html
│ │ ├── slotted-drawer-demo.js
│ │ └── test.html
│ ├── dropdown-select
│ │ ├── _spec.scss
│ │ ├── index.html
│ │ ├── select-demo.js
│ │ └── test.html
│ ├── email
│ │ ├── _spec.scss
│ │ ├── email-control-demo.js
│ │ ├── index.html
│ │ └── test.html
│ ├── file
│ │ ├── _spec.scss
│ │ ├── drop-zone-demo.js
│ │ ├── file-input-demo.js
│ │ ├── file-tile-demo.js
│ │ ├── index.html
│ │ ├── test-drop-fence.html
│ │ ├── test-drop-zone.html
│ │ ├── test-file-input.html
│ │ └── test-file-tile.html
│ ├── grid
│ │ ├── _index.scss
│ │ └── index.html
│ ├── icon
│ │ ├── _index.scss
│ │ ├── icon-demo.js
│ │ └── index.html
│ ├── index.js
│ ├── layout
│ │ ├── horizontal-layout.html
│ │ ├── index.html
│ │ └── vertical-layout.html
│ ├── list
│ │ ├── index.html
│ │ └── list-demo.js
│ ├── loader
│ │ ├── index.html
│ │ ├── loader-demo.js
│ │ └── test-progress.html
│ ├── menu
│ │ ├── _spec.scss
│ │ ├── index.html
│ │ ├── test-positioning.html
│ │ └── test.html
│ ├── modal
│ │ ├── index.html
│ │ ├── modal-demo.js
│ │ └── test.html
│ ├── navigation
│ │ ├── _index.scss
│ │ └── index.html
│ ├── pagination
│ │ └── index.html
│ ├── panel
│ │ ├── _index.scss
│ │ ├── _spec.scss
│ │ ├── index.html
│ │ ├── panel-demo.js
│ │ └── test.html
│ ├── password
│ │ ├── _spec.scss
│ │ ├── index.html
│ │ ├── password-demo.js
│ │ └── test.html
│ ├── pill
│ │ ├── index.html
│ │ ├── pill-demo.js
│ │ └── test.html
│ ├── popover
│ │ ├── _spec.scss
│ │ ├── index.html
│ │ ├── popover-demo.js
│ │ └── test.html
│ ├── radio
│ │ ├── _spec.scss
│ │ ├── index.html
│ │ ├── radio-basic-demo.js
│ │ ├── radio-demo.js
│ │ └── test.html
│ ├── reveal
│ │ ├── index.html
│ │ └── reveal-demo.js
│ ├── search
│ │ ├── _spec.scss
│ │ ├── index.html
│ │ ├── search-demo.js
│ │ └── test.html
│ ├── secnav
│ │ ├── index.html
│ │ ├── secnav-demo.js
│ │ └── test.html
│ ├── selector-strip
│ │ └── index.html
│ ├── stepper
│ │ ├── index.html
│ │ └── stepper-demo.js
│ ├── switch
│ │ ├── _spec.scss
│ │ ├── error-switch-demo.js
│ │ ├── index.html
│ │ ├── switch-demo.js
│ │ └── test.html
│ ├── table
│ │ ├── index.html
│ │ └── table-demo.js
│ ├── tabset
│ │ ├── _index.scss
│ │ ├── index.html
│ │ ├── tabset-demo.js
│ │ └── test.html
│ ├── text-input
│ │ ├── _spec.scss
│ │ ├── index.html
│ │ ├── test.html
│ │ └── text-input-demo.js
│ ├── textarea
│ │ ├── _spec.scss
│ │ ├── index.html
│ │ ├── test.html
│ │ └── textarea-demo.js
│ ├── toast
│ │ ├── index.html
│ │ └── toast-demo.js
│ ├── toggle
│ │ ├── _spec.scss
│ │ ├── index.html
│ │ ├── test.html
│ │ └── toggle-demo.js
│ ├── tooltip
│ │ ├── _index.scss
│ │ ├── index.html
│ │ ├── test.html
│ │ └── tooltip-demo.js
│ ├── topnav
│ │ ├── index.html
│ │ ├── test.html
│ │ └── topnav-demo.js
│ └── typography
│ │ ├── _index.scss
│ │ ├── index.html
│ │ └── test.html
├── docs.js
├── docs.less
├── elements
│ ├── hx-accordion-panel
│ │ └── index.html
│ ├── hx-accordion
│ │ └── index.html
│ ├── hx-alert
│ │ └── index.html
│ ├── hx-beacon
│ │ └── index.html
│ ├── hx-busy
│ │ └── index.html
│ ├── hx-checkbox-control
│ │ └── index.html
│ ├── hx-checkbox
│ │ └── index.html
│ ├── hx-disclosure
│ │ └── index.html
│ ├── hx-div
│ │ └── index.html
│ ├── hx-drawer
│ │ └── index.html
│ ├── hx-drop-fence
│ │ └── index.html
│ ├── hx-drop-zone
│ │ └── index.html
│ ├── hx-email-control
│ │ └── index.html
│ ├── hx-error
│ │ └── index.html
│ ├── hx-file-icon
│ │ └── index.html
│ ├── hx-file-input
│ │ └── index.html
│ ├── hx-file-tile
│ │ └── index.html
│ ├── hx-icon
│ │ └── index.html
│ ├── hx-menu
│ │ └── index.html
│ ├── hx-menuitem
│ │ └── index.html
│ ├── hx-modal
│ │ └── index.html
│ ├── hx-password-control
│ │ └── index.html
│ ├── hx-pill
│ │ └── index.html
│ ├── hx-popover
│ │ └── index.html
│ ├── hx-progress
│ │ └── index.html
│ ├── hx-radio-control
│ │ └── index.html
│ ├── hx-radio-set
│ │ └── index.html
│ ├── hx-radio
│ │ └── index.html
│ ├── hx-reveal
│ │ └── index.html
│ ├── hx-search-assistance
│ │ └── index.html
│ ├── hx-search-control
│ │ └── index.html
│ ├── hx-search
│ │ └── index.html
│ ├── hx-select-control
│ │ └── index.html
│ ├── hx-select
│ │ └── index.html
│ ├── hx-status
│ │ └── index.html
│ ├── hx-switch-control
│ │ └── index.html
│ ├── hx-switch
│ │ └── index.html
│ ├── hx-tab
│ │ └── index.html
│ ├── hx-tabcontent
│ │ └── index.html
│ ├── hx-tablist
│ │ └── index.html
│ ├── hx-tabpanel
│ │ └── index.html
│ ├── hx-tabset
│ │ └── index.html
│ ├── hx-text-control
│ │ └── index.html
│ ├── hx-textarea-control
│ │ └── index.html
│ ├── hx-tile
│ │ └── index.html
│ ├── hx-toast
│ │ └── index.html
│ ├── hx-toggle-control
│ │ └── index.html
│ ├── hx-toggle
│ │ └── index.html
│ └── hx-tooltip
│ │ └── index.html
├── files
│ ├── easteregg.txt
│ ├── horizontal-layout-template.html
│ └── vertical-layout-template.html
├── guides
│ ├── faq
│ │ └── index.html
│ ├── getting-started
│ │ └── index.html
│ ├── polyfills
│ │ └── index.html
│ └── react-compatibility
│ │ └── index.html
├── images
│ ├── 200x150.png
│ ├── favicon.png
│ ├── helix-logo.svg
│ └── thumbs
│ │ ├── horizontal-layout.png
│ │ └── vertical-layout.png
├── index.html
├── index.scss
├── scripts
│ └── test-helpers.js
└── vendor
│ ├── bundles
│ ├── webcomponents-ce.js
│ ├── webcomponents-ce.js.map
│ ├── webcomponents-sd-ce-pf.js
│ ├── webcomponents-sd-ce-pf.js.map
│ ├── webcomponents-sd-ce.js
│ ├── webcomponents-sd-ce.js.map
│ ├── webcomponents-sd.js
│ └── webcomponents-sd.js.map
│ ├── custom-elements-es5-adapter.js
│ ├── webcomponents-bundle.js
│ ├── webcomponents-bundle.js.map
│ └── webcomponents-loader.js
├── git-hooks
├── commit-msg
├── commit
│ ├── errors.js
│ ├── index.js
│ └── types.js
├── pre-commit
└── util
│ └── formatting.js
├── gulpfile.esm.js
├── jsdoc.conf.json
├── karma-init.js
├── karma-sauce-init.js
├── karma.conf.js
├── karma.sauce.config.js
├── netlify.toml
├── package.json
├── scripts
├── _config
│ └── index.js
├── _generate
│ ├── context.js
│ ├── index.js
│ ├── markup.js
│ └── nunjucks.js
├── _publish
│ └── publishDocs.js
├── _util
│ ├── copy.js
│ └── index.js
├── build.js
├── clean.js
├── cleanPublic.js
├── generate.js
├── lint.sh
├── publish.js
├── revert-git-hooks.sh
├── serve.js
├── setup-git-hooks.sh
└── start.js
├── src
├── _bundle.es5.js
├── _bundle.es6.js
├── elements
│ ├── _base.scss
│ ├── _has-arrow.scss
│ ├── hx-accordion-panel
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-accordion
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-alert
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-beacon
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-busy
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-checkbox-control
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-checkbox-set
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-checkbox
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-disclosure
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-div
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-drawer
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-drop-fence
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-drop-zone
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-email-control
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-error
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-file-control
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-file-icon
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-file-input
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-file-tile
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-icon
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-menu
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-menuitem
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-modal
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-password-control
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-pill
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-popover
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-progress
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-radio-control
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-radio-set
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-radio
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-reveal
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-search-assistance
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-search-control
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-search
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-select-control
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-select
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-switch-control
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-switch
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-tab
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-tabcontent
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-tablist
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-tabpanel
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-tabset
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-text-control
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-textarea-control
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-toast
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-toggle-control
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-toggle
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── hx-tooltip
│ │ ├── _shadow.html
│ │ ├── _shadow.scss
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── index.js
│ ├── index.spec.js
│ └── traits
│ │ ├── Positionable.js
│ │ ├── Positionable.spec.js
│ │ ├── Revealable.js
│ │ └── Revealable.spec.js
├── images
│ ├── asterisk.svg
│ └── icons
│ │ ├── account.svg
│ │ ├── angle-bottom.svg
│ │ ├── angle-down.svg
│ │ ├── angle-end.svg
│ │ ├── angle-left.svg
│ │ ├── angle-right.svg
│ │ ├── angle-start.svg
│ │ ├── angle-top.svg
│ │ ├── angle-up.svg
│ │ ├── bell.svg
│ │ ├── billing.svg
│ │ ├── calendar.svg
│ │ ├── chart.svg
│ │ ├── checkmark-circle.svg
│ │ ├── checkmark.svg
│ │ ├── clock.svg
│ │ ├── cog.svg
│ │ ├── copy.svg
│ │ ├── critical.svg
│ │ ├── download.svg
│ │ ├── envelope.svg
│ │ ├── exclamation-circle.svg
│ │ ├── exclamation-diamond.svg
│ │ ├── exclamation-triangle.svg
│ │ ├── external-link.svg
│ │ ├── file.svg
│ │ ├── filter.svg
│ │ ├── fish-hook.svg
│ │ ├── flag.svg
│ │ ├── globe.svg
│ │ ├── grid.svg
│ │ ├── heartbeat-fill.svg
│ │ ├── heartbeat-outline.svg
│ │ ├── help-circle.svg
│ │ ├── info-circle.svg
│ │ ├── information.svg
│ │ ├── input-file.svg
│ │ ├── kbd-arrow-down.svg
│ │ ├── kbd-arrow-left.svg
│ │ ├── kbd-arrow-right.svg
│ │ ├── kbd-arrow-up.svg
│ │ ├── kbd-capslock.svg
│ │ ├── kbd-command.svg
│ │ ├── kbd-delete.svg
│ │ ├── kbd-eject.svg
│ │ ├── kbd-option.svg
│ │ ├── kbd-return.svg
│ │ ├── kbd-shift.svg
│ │ ├── kbd-space.svg
│ │ ├── kbd-tab.svg
│ │ ├── key.svg
│ │ ├── list.svg
│ │ ├── lock.svg
│ │ ├── mime-archive.svg
│ │ ├── mime-audio.svg
│ │ ├── mime-code.svg
│ │ ├── mime-data.svg
│ │ ├── mime-image.svg
│ │ ├── mime-system.svg
│ │ ├── mime-text.svg
│ │ ├── mime-video.svg
│ │ ├── minus-circle.svg
│ │ ├── minus.svg
│ │ ├── ok.svg
│ │ ├── paperclip.svg
│ │ ├── payment.svg
│ │ ├── pencil.svg
│ │ ├── pending.svg
│ │ ├── phone.svg
│ │ ├── plus-or-minus.svg
│ │ ├── plus.svg
│ │ ├── redo.svg
│ │ ├── search.svg
│ │ ├── server-config.svg
│ │ ├── server-incident.svg
│ │ ├── server.svg
│ │ ├── shield-lock.svg
│ │ ├── sort-down.svg
│ │ ├── sort-up.svg
│ │ ├── sort.svg
│ │ ├── support.svg
│ │ ├── tag.svg
│ │ ├── ticketing.svg
│ │ ├── times-circle.svg
│ │ ├── times.svg
│ │ ├── trash.svg
│ │ ├── unavailable.svg
│ │ ├── undo.svg
│ │ ├── upload.svg
│ │ ├── user.svg
│ │ └── warning.svg
├── index.js
├── interfaces
│ ├── HXElement
│ │ ├── index.js
│ │ └── index.spec.js
│ └── HXFormControlElement
│ │ ├── index.js
│ │ └── index.spec.js
├── less
│ ├── components.less
│ ├── components
│ │ ├── box
│ │ │ └── index.less
│ │ ├── file
│ │ │ ├── hx-file-control.less
│ │ │ └── index.less
│ │ └── grid
│ │ │ └── index.less
│ ├── index.less
│ ├── mixins.less
│ ├── mixins
│ │ ├── microsoft.less
│ │ ├── mozilla.less
│ │ ├── standard.less
│ │ └── webkit.less
│ └── vars.less
├── polyfills
│ ├── ChildNode
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── Element
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── index.js
│ └── index.spec.js
├── scss
│ ├── _config.scss
│ ├── _mixins.scss
│ ├── _overrides.scss
│ ├── _tokens.scss
│ ├── _vars-legacy.scss
│ ├── _vars.scss
│ ├── base
│ │ ├── _index.scss
│ │ ├── _links.scss
│ │ └── _typography.scss
│ ├── components
│ │ ├── _config.scss
│ │ ├── _index.scss
│ │ ├── accordion
│ │ │ ├── _index.scss
│ │ │ └── _stepper.scss
│ │ ├── alert
│ │ │ └── index.scss
│ │ ├── badge
│ │ │ └── index.scss
│ │ ├── beacon
│ │ │ └── index.scss
│ │ ├── box
│ │ │ ├── _config.scss
│ │ │ ├── _deprecated.scss
│ │ │ ├── _hx-div.scss
│ │ │ ├── _hxBox.scss
│ │ │ └── _index.scss
│ │ ├── breadcrumb
│ │ │ └── index.scss
│ │ ├── button
│ │ │ ├── _button.scss
│ │ │ ├── _buttonBar.scss
│ │ │ ├── _buttonSet.scss
│ │ │ ├── _cogButton.scss
│ │ │ ├── _config.scss
│ │ │ ├── _deprecated.scss
│ │ │ ├── _index.scss
│ │ │ └── mixins
│ │ │ │ ├── _hxButton.scss
│ │ │ │ └── _hxButtonBar.scss
│ │ ├── checkbox
│ │ │ ├── _config.scss
│ │ │ ├── _index.scss
│ │ │ └── mixins
│ │ │ │ ├── _hxCheckboxControl.scss
│ │ │ │ └── _hxCheckboxFacade.scss
│ │ ├── choice-tile
│ │ │ ├── _index.scss
│ │ │ └── mixins
│ │ │ │ └── _hxChoiceTile.scss
│ │ ├── drawer
│ │ │ └── _index.scss
│ │ ├── dropdown-select
│ │ │ ├── _config.scss
│ │ │ ├── index.scss
│ │ │ └── mixins
│ │ │ │ ├── SelectControl.scss
│ │ │ │ ├── SelectFacade.scss
│ │ │ │ └── SelectReset.scss
│ │ ├── email
│ │ │ └── _index.scss
│ │ ├── file
│ │ │ ├── _config.scss
│ │ │ ├── _hx-drop-fence.scss
│ │ │ ├── _hx-drop-zone.scss
│ │ │ ├── _hx-file-control.scss
│ │ │ ├── _hx-file-icon.scss
│ │ │ ├── _hx-file-tile.scss
│ │ │ ├── _index.scss
│ │ │ └── mixins
│ │ │ │ └── hxFileControl.scss
│ │ ├── form
│ │ │ ├── _config.scss
│ │ │ ├── _deprecated.scss
│ │ │ ├── _index.scss
│ │ │ ├── _reset.scss
│ │ │ └── mixins
│ │ │ │ ├── _fieldName.scss
│ │ │ │ ├── _helpText.scss
│ │ │ │ ├── _input.scss
│ │ │ │ ├── _placeholder.scss
│ │ │ │ └── _textControl.scss
│ │ ├── grid
│ │ │ ├── _config.scss
│ │ │ └── _index.scss
│ │ ├── icon
│ │ │ └── index.scss
│ │ ├── layout
│ │ │ └── _index.scss
│ │ ├── list
│ │ │ └── _index.scss
│ │ ├── loader
│ │ │ ├── _hx-busy.scss
│ │ │ ├── _hx-progress.scss
│ │ │ └── _index.scss
│ │ ├── menu
│ │ │ └── _index.scss
│ │ ├── modal
│ │ │ └── _index.scss
│ │ ├── navigation
│ │ │ └── _index.scss
│ │ ├── pagination
│ │ │ └── _index.scss
│ │ ├── panel
│ │ │ └── _index.scss
│ │ ├── password-input
│ │ │ └── _index.scss
│ │ ├── pill
│ │ │ └── _index.scss
│ │ ├── popover
│ │ │ └── _index.scss
│ │ ├── radio
│ │ │ ├── _config.scss
│ │ │ ├── _index.scss
│ │ │ └── mixins
│ │ │ │ ├── _hxRadioControl.scss
│ │ │ │ └── _hxRadioFacade.scss
│ │ ├── reveal
│ │ │ └── _index.scss
│ │ ├── search
│ │ │ ├── SearchFacade.scss
│ │ │ └── _index.scss
│ │ ├── secnav
│ │ │ ├── _config.scss
│ │ │ ├── index.scss
│ │ │ └── mixins
│ │ │ │ └── _secNavControl.scss
│ │ ├── selector-strip
│ │ │ ├── _hxSelector.scss
│ │ │ └── _index.scss
│ │ ├── switch
│ │ │ ├── _config.scss
│ │ │ ├── _index.scss
│ │ │ └── mixins
│ │ │ │ └── _hxSwitchControl.scss
│ │ ├── table
│ │ │ └── _index.scss
│ │ ├── tabset
│ │ │ └── _index.scss
│ │ ├── text-input
│ │ │ └── _index.scss
│ │ ├── textarea
│ │ │ └── _index.scss
│ │ ├── toast
│ │ │ └── _index.scss
│ │ ├── toggle
│ │ │ ├── _config.scss
│ │ │ ├── _index.scss
│ │ │ └── mixins
│ │ │ │ └── _hxToggleControl.scss
│ │ ├── tooltip
│ │ │ └── _index.scss
│ │ ├── topnav
│ │ │ ├── _config.scss
│ │ │ ├── index.scss
│ │ │ └── mixins
│ │ │ │ └── _topNavControl.scss
│ │ └── typography
│ │ │ ├── _hljs.scss
│ │ │ └── _index.scss
│ ├── helpers
│ │ ├── _alignment.scss
│ │ ├── _index.scss
│ │ └── _wrapping.scss
│ ├── index.scss
│ └── reset
│ │ ├── _html5.scss
│ │ └── _index.scss
└── utils
│ ├── alignment
│ ├── index.js
│ └── index.spec.js
│ ├── icons
│ ├── index.js
│ └── index.spec.js
│ ├── index.js
│ ├── index.spec.js
│ └── offset
│ ├── index.js
│ └── index.spec.js
├── tasks
├── archive
│ ├── helix-ui.js
│ ├── icons.js
│ └── index.js
├── bundle
│ ├── browser.js
│ ├── index.js
│ ├── module.js
│ └── styles.js
├── config.js
├── index.js
└── rollup
│ ├── index.js
│ ├── plugin-sass.js
│ └── plugins.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "modules": false
7 | }
8 | ]
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # top-most EditorConfig file
2 | root = true
3 |
4 | # (defaults) applies to all files
5 | [*]
6 | charset = utf-8
7 | end_of_line = lf
8 | indent_size = 2
9 | indent_style = space
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 |
13 | # JavaScript Overrides
14 | [*.{js,mjs}]
15 | indent_size = 4
16 |
17 | # TypeScript Overrides
18 | [*.{ts}]
19 | indent_size = 4
20 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | # directories
2 | bin/*
3 | lib/*
4 | scripts/*
5 | node_modules/*
6 | public/*
7 | test/*
8 |
9 | # spec files
10 | src/**/*.spec.js
11 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.eslintrc.prod.json",
3 | "rules": {
4 | "array-bracket-newline": 1,
5 | "array-bracket-spacing": 1,
6 | "array-element-newline": 1,
7 | "brace-style": 1,
8 | "camelcase": 1,
9 | "comma-dangle": 1,
10 | "comma-style": 1,
11 | "complexity": 1,
12 | "curly": 1,
13 | "eol-last": 1,
14 | "eqeqeq": 1,
15 | "indent": 1,
16 | "keyword-spacing": 1,
17 | "max-depth": 1,
18 | "max-len": 1,
19 | "new-cap": 1,
20 | "no-bitwise": 1,
21 | "no-caller": 1,
22 | "no-console": 1,
23 | "no-empty": 1,
24 | "no-multiple-empty-lines": 1,
25 | "no-undef": 1,
26 | "no-unused-expressions": 1,
27 | "no-unused-vars": 1,
28 | "no-use-before-define": 1,
29 | "object-curly-spacing": 1,
30 | "quotes": 1,
31 | "semi": 1,
32 | "space-before-function-paren": 1,
33 | "space-in-parens": 1,
34 | "space-infix-ops": 1,
35 | "space-unary-ops": 1,
36 | "wrap-iife": 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug Report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | ## Describe the Bug
8 | A clear and concise description of what the bug is.
9 |
10 | ## Steps to Reproduce
11 | Steps to reproduce the behavior:
12 |
13 | 1. Go to '...'
14 | 2. Click on '...'
15 | 3. Scroll down to '...'
16 | 4. ...
17 | 5. Dogs and cats living together!
18 |
19 | ## Expected behavior
20 | A clear and concise description of what you expected to happen.
21 |
22 | ## Screenshots
23 | If applicable, add screenshots to help explain your problem.
24 |
25 | ## Environment
26 | Please complete the following information:
27 |
28 | - Device: [e.g. Desktop, Laptop, iPhone6, etc.]
29 | - OS: [e.g. iOS]
30 | - Browser: [e.g. chrome, safari]
31 | - Version: [e.g. 22]
32 |
33 | ## Additional Context
34 | Add any other context about the problem here.
35 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | **[Remove this line]** _Provide a short description._
4 |
5 | ### What are the relevant story cards/tickets? Any additional PRs or other references?
6 |
7 | Jira:
8 |
9 | ## Before you request a review for this PR:
10 |
11 | - [ ] For UI changes, did you manually test in recent versions of modern browsers (Chrome, Firefox, and Safari)?
12 | - [ ] For UI changes, did you manually test in IE11 and legacy Edge?
13 | - [ ] Did you add component tests for any new code?
14 | - [ ] Did you run the component unit tests via `yarn test` to ensure all tests passed?
15 | - [ ] Did you include a screenshot of the component tests?
16 | - [ ] If you changed/added functionality, did you update the demo page and documentation?
17 | - [ ] If needed, did you add or modify the demo test page to test the changed/added functionality?
18 | - [ ] Did you assign reviewers?
19 | - [ ] In Jira, have you linked to this PR on the ticket(s)?
20 |
--------------------------------------------------------------------------------
/.github/workflows/browser-tests.yml:
--------------------------------------------------------------------------------
1 | # GitHub Action Worflow to support HelixUI SauceLabs Browser Tests
2 |
3 | name: HelixUI SauceLabs Tests
4 |
5 | on:
6 | push:
7 | branches:
8 | - master
9 | pull_request:
10 | branches:
11 | - master
12 |
13 | jobs:
14 |
15 | tests:
16 | name: SauceLabs Browser Tests
17 |
18 | runs-on: ubuntu-latest
19 | if: ${{ !github.FORK }} # if PR/Push from a fork, exit script
20 |
21 | steps:
22 | - uses: actions/checkout@v2.3.4
23 | - name: SauceLabs Browser Tests
24 | uses: actions/setup-node@v2.1.5
25 | with:
26 | node-version: 12.x
27 | # running this test on TravisCI vs GH Actions
28 | # - run: yarn install:clean
29 | # - run: yarn compile --prod
30 |
31 | # - run: yarn test:sauce
32 | # env:
33 | # SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
34 | # SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
35 | # GA_RUN_ID: github-${{ github.WORKFLOW }}-${{ github.RUN_NUMBER }}-RUN-${{ github.RUN_ID }}
36 | # if: ${{ env.SAUCE_USERNAME != null }}
37 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | # Helix-UI CI Pipeline - GitHub Actions Workflow
2 |
3 | name: HelixUI CI Build Pipeline
4 |
5 | on:
6 | push:
7 | branches:
8 | - master
9 | pull_request:
10 | branches:
11 | - master
12 |
13 | jobs:
14 | build:
15 | name: Pull Request or Push Action
16 |
17 | runs-on: ubuntu-latest
18 |
19 | steps:
20 | - uses: actions/checkout@v2.3.4
21 | - name: HelixUI Build and Test
22 | uses: actions/setup-node@v2.1.5
23 | with:
24 | node-version: 12.x
25 |
26 | - run: npm install -g yarn
27 | - run: yarn install:clean
28 | - run: yarn lint
29 | - run: yarn generate
30 | - run: yarn test:build
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | *.swp
4 | debug.log
5 | package-lock.json
6 |
7 | # Generated Files/Directories
8 | db.json
9 | *.log
10 | public/
11 | .deploy*/
12 | dist/
13 | lib/
14 | _tmp/
15 |
16 | # Removing Coverage Reports folder created.
17 | coverage
18 | .nyc_output
19 | /.idea
20 |
--------------------------------------------------------------------------------
/.node-version:
--------------------------------------------------------------------------------
1 | 12.10.0
2 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://registry.npmjs.org/
2 |
3 | message = "publish(npm): v%s [skip ci]"
4 | preid = "rc"
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | dist: xenial
2 | os:
3 | - linux
4 | language: node_js
5 | node_js:
6 | - '12'
7 | notifications:
8 | email: false
9 | addons:
10 | firefox: latest
11 | chrome: stable
12 | branches:
13 | only:
14 | - master
15 | cache:
16 | yarn: true
17 | jobs:
18 | include:
19 | - stage: component-tests
20 | script:
21 | - yarn lint
22 | - yarn generate
23 | - yarn compile --prod
24 | - |
25 | if [ $TRAVIS_BRANCH != false ] && [ $TRAVIS_SECURE_ENV_VARS == true ]; then
26 | echo "Running extended test suite...";
27 | yarn test;
28 | # TBD - need to investigate SL flakiness
29 | # echo "Running Sauce tests...";
30 | # yarn test:sauce || travis_terminate 1;
31 | else
32 | echo "Running standard test suite...";
33 | yarn test || travis_terminate 1;
34 | fi
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2017-2021 Rackspace US, Inc.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/docs/_banner.scss:
--------------------------------------------------------------------------------
1 | // currently used by test page layout to display a warning to readers
2 | .banner {
3 | -ms-grid-columns: auto 1fr;
4 | -ms-grid-row-align: baseline;
5 | align-items: baseline;
6 | background-color: $gray-0;
7 | border: 2px solid currentColor;
8 | color: $gray-950;
9 | display: -ms-grid;
10 | display: grid;
11 | grid-template-areas: 'icon content';
12 | grid-template-columns: auto 1fr;
13 | padding: 1rem;
14 |
15 | > * {
16 | margin: 0;
17 | }
18 |
19 | &.warning {
20 | background-color: $yellow-500;
21 | border: 2px solid $yellow-900;
22 | }
23 | }
24 |
25 | .banner__icon {
26 | -ms-grid-column: 1;
27 | -ms-grid-row: 1;
28 | grid-area: icon;
29 | margin-right: 1rem; // because IE
30 | }
31 |
32 | .banner__body {
33 | -ms-grid-column: 2;
34 | -ms-grid-row: 1;
35 | grid-area: content;
36 | }
37 |
38 | @include supports-grid {
39 | .banner {
40 | grid-gap: 1rem;
41 | }
42 |
43 | .banner__icon {
44 | margin: 0; // because IE
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/docs/_config.js:
--------------------------------------------------------------------------------
1 | // Tell Vue to ignore HelixUI custom elements.
2 | Vue.config.ignoredElements = [ /^hx-/ ];
3 |
--------------------------------------------------------------------------------
/docs/_darkButtons.scss:
--------------------------------------------------------------------------------
1 | .hxBtn,
2 | a[href].hxBtn {
3 | &.beta-hxDark {
4 | border-color: $cyan-500;
5 | color: $cyan-500;
6 |
7 | &:hover {
8 | color: $gray-0;
9 | }
10 |
11 | &:active {
12 | border-color: transparent;
13 | }
14 |
15 | &:focus {
16 | box-shadow: 0 0 4px 2px rgba($cyan-500, 0.6);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/docs/_data/positions.json5:
--------------------------------------------------------------------------------
1 | {
2 | withoutArrow: [
3 | 'top-start',
4 | 'top-left',
5 | 'top',
6 | 'top-right',
7 | 'top-end',
8 | 'bottom-start',
9 | 'bottom-left',
10 | 'bottom',
11 | 'bottom-right',
12 | 'bottom-end',
13 | 'right-start',
14 | 'right-top',
15 | 'right',
16 | 'right-bottom',
17 | 'right-end',
18 | 'left-start',
19 | 'left-top',
20 | 'left',
21 | 'left-bottom',
22 | 'left-end',
23 | ],
24 | withArrow: [
25 | 'top-left',
26 | 'top',
27 | 'top-right',
28 | 'bottom-left',
29 | 'bottom',
30 | 'bottom-right',
31 | 'right-top',
32 | 'right',
33 | 'right-bottom',
34 | 'left-top',
35 | 'left',
36 | 'left-bottom',
37 | ],
38 | }
39 |
--------------------------------------------------------------------------------
/docs/_nunjucks/toc.filter.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const cheerio = require('cheerio');
4 |
5 | function tocFilter (str, options) {
6 | options = options || {};
7 |
8 | const $ = cheerio.load(str);
9 | const headingSelectors = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
10 |
11 | // we only care about h1-6[id] or h1-6[data-id]
12 | const mappedHeadineSelectors = headingSelectors.map( selector => {
13 | return [
14 | `${selector}[id]:not(.skip-toc)`,
15 | `${selector}[data-id]:not(.skip-toc)`,
16 | ].join(',');
17 | });
18 |
19 | const headings = $(mappedHeadineSelectors.join(','));
20 |
21 | // STOP, if no TOC headings found
22 | if (!headings.length) {
23 | return '';
24 | }
25 |
26 | let items = [];
27 |
28 | headings.each(function () {
29 | let anchor = $(this).attr('id') || $(this).data()['id'];
30 |
31 | // do not create list item if there is nowhere to anchor
32 | if (!anchor) {
33 | return;
34 | }
35 |
36 | items.push(`
37 | ${ $(this).text() }
38 | `);
39 | });
40 |
41 | return items.join('\n');
42 | }//tocFilter
43 |
44 | module.exports = tocFilter;
45 |
--------------------------------------------------------------------------------
/docs/_shame.scss:
--------------------------------------------------------------------------------
1 | dl:not(.hxList) {
2 | dd {
3 | margin-bottom: 0.5em;
4 | margin-left: 1em;
5 | }
6 | }
7 |
8 | /* Beta Auto Grid Styles */
9 | .hxRow.hxAuto > .hxCol { flex-grow: 0; }
10 | .hxRow .hxCol.hxAuto { flex: 0 0 auto; }
11 |
12 | // keep line size at a readable length
13 | p.comfortable,
14 | header > p {
15 | max-width: 80ch;
16 | }
17 |
--------------------------------------------------------------------------------
/docs/_templates/component.njk:
--------------------------------------------------------------------------------
1 | {% extends 'application.njk' %}
2 | {% set hasSiderail = true %}
3 | {% set mainClass = 'component-content' %}
4 |
--------------------------------------------------------------------------------
/docs/_templates/guide.njk:
--------------------------------------------------------------------------------
1 | {% extends 'application.njk' %}
2 | {% set hasSiderail = true %}
3 | {% set mainClass = 'guide-content' %}
4 |
--------------------------------------------------------------------------------
/docs/_templates/no-frame.njk:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {% if page.title %}{{page.title}} - {% endif %}{{site.title}}
5 |
6 |
7 |
8 |
9 |
10 |
11 | {# HelixUI Styles (generated from src/) #}
12 |
13 | {# Documentation Styles (generated from docs/) #}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {% block content %}
22 | {# page content goes here #}
23 | {% endblock %}
24 |
25 |
26 | {# Vue for Interactive Demos #}
27 |
28 | {# HelixUI Behavior (generated from src/) #}
29 |
30 | {# Documentation Behavior (generated from docs/) #}
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/docs/_templates/partials/app_nav.njk:
--------------------------------------------------------------------------------
1 | {% macro renderItem(item, path) %}
2 | {% if path %}
3 | {% set normpath = path + '/' + item.path %}
4 | {% else %}
5 | {% set normpath = item.path %}
6 | {% endif %}
7 |
8 | {% if item.children %}
9 | {{ section(item) }}
10 | {% else %}
11 | {{ link(item.label, normpath) }}
12 | {% endif %}
13 | {% endmacro %}
14 |
15 | {% macro link(label, href) %}
16 | {% set isCurrentLink = page.path.indexOf(href + '/') === 0 %}
17 |
18 | {{label}}
19 |
20 | {% endmacro %}
21 |
22 | {% macro section(section) %}
23 | {% set isCurrentCategory = (page.path.indexOf(section.path) === 0) %}
24 | {% set revealId = 'nav-' + section.path %}
25 |
26 |
29 | {{ section.label }}
30 |
31 |
32 |
33 | {% for child in section.children %}
34 | {{renderItem(child, section.path)}}
35 | {% endfor %}
36 |
37 | {% endmacro %}
38 |
39 | {% for item in data.nav %}
40 | {{renderItem(item)}}
41 | {% endfor %}
42 |
--------------------------------------------------------------------------------
/docs/_templates/partials/lorem-nav.njk:
--------------------------------------------------------------------------------
1 | Link 1
2 | Link 2
3 | Link 3
4 |
5 |
6 | Section 1
7 |
8 |
9 |
10 | Link 1-1
11 | Link 1-2
12 | Link 1-3
13 |
14 |
15 | Section 2
16 |
17 |
18 |
19 | Link 2-1
20 | Link 2-2
21 | Link 2-3
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/docs/_templates/partials/min-version.njk:
--------------------------------------------------------------------------------
1 |
2 | v{{page.minver}}+
3 |
4 |
5 |
6 | HelixUI v{{page.minver}} or later required
7 |
8 |
--------------------------------------------------------------------------------
/docs/_templates/partials/see-also.njk:
--------------------------------------------------------------------------------
1 |
2 | See Also
3 |
4 | {% for href,label in page.also %}
5 | {{label}}
6 | {% endfor %}
7 |
8 |
9 |
--------------------------------------------------------------------------------
/docs/_templates/props/Positionable/optimumPosition.njk:
--------------------------------------------------------------------------------
1 | optimumPosition {String|undefined}
2 |
3 |
4 | Optimum position determined by internal positioning algorithm.
5 |
6 |
7 | It will return undefined if {{page.title}}
8 | hasn't been repositioned.
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/_templates/props/Positionable/relativeElement.njk:
--------------------------------------------------------------------------------
1 |
2 | relativeElement {HTMLElement}
3 | read-only
4 |
5 |
6 |
7 | HTML element used as a point of reference for calculating the fixed
8 | position of the {{page.title}}
.
9 |
10 |
11 | If the relative-to
attribute is defined, this will return
12 | the first element whose ID matches the relativeTo
property.
13 | Otherwise, it will return the value of controlElement
.
14 |
15 |
16 |
--------------------------------------------------------------------------------
/docs/_templates/props/Positionable/relativeTo.njk:
--------------------------------------------------------------------------------
1 | relativeTo {String}
2 |
3 |
4 | A string corresponding to the ID of the relative element .
5 |
6 |
7 |
8 | Reflects the relative-to
attribute.
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/_templates/props/Revealable/open.njk:
--------------------------------------------------------------------------------
1 | open {Boolean [false]}
2 |
3 |
4 | Indicates whether or not the {{page.title}}
5 | should be displayed.
6 |
7 |
8 |
--------------------------------------------------------------------------------
/docs/_templates/test.njk:
--------------------------------------------------------------------------------
1 | {% extends 'application.njk' %}
2 | {% set hasSiderail = true %}
3 | {% set mainClass = 'test-content' %}
4 |
5 | {% block banner %}
6 | {# WARNING BANNER #}
7 |
8 |
9 |
10 | UI TESTING:
11 | Do not replicate anything on this page within your application.
12 |
13 |
14 | {% endblock %}
15 |
--------------------------------------------------------------------------------
/docs/_test-content.scss:
--------------------------------------------------------------------------------
1 | /* ----- Test Page Styling ----- */
2 | .test-content {
3 | border: 0.5rem solid $yellow-900;
4 |
5 | section {
6 | > section {
7 | margin-bottom: 2rem;
8 | margin-left: 2rem;
9 | }
10 |
11 | > table {
12 | border: 1px solid $gray-400;
13 |
14 | td, th {
15 | padding: 1em;
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/docs/_toc.scss:
--------------------------------------------------------------------------------
1 | // table of contents
2 | .toc {
3 | align-items: flex-start;
4 | display: flex;
5 | flex-direction: column;
6 | position: -webkit-sticky;
7 | position: sticky;
8 | top: 1rem;
9 |
10 | > a {
11 | font-weight: 500;
12 | margin-bottom: 0.5rem;
13 | text-decoration: none;
14 | }
15 |
16 | // hide if no grid support
17 | .top-link {
18 | font-size: 0.875rem;
19 | font-weight: 300;
20 |
21 | // hide if stacked layout
22 | display: none;
23 | // show if grid layout
24 | @include supports-grid {
25 | display: block;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/docs/_util.js:
--------------------------------------------------------------------------------
1 | function stripIndent (rawString) {
2 | const match = rawString.match(/^[ \t]*(?=\S)/gm);
3 |
4 | if (!match) {
5 | return rawString;
6 | }
7 |
8 | const minIndent = Math.min.apply(Math, match.map(x => x.length));
9 |
10 | const reMinIndent = new RegExp(`^[ \\t]{${minIndent}}`, 'gm');
11 |
12 | let strReindented = rawString;
13 | if (minIndent > 0) {
14 | strReindented = rawString.replace(reMinIndent, '');
15 | }
16 |
17 | return strReindented.trim();
18 | }//stripIndent()
19 |
20 | function snippet (raw) {
21 | // https://regex101.com/r/hKMzZP/4
22 | let normalized = raw.replace(/(\s+^\s+$|\s+(?=>))/gm, '');
23 | return stripIndent(normalized);
24 | }
25 |
26 | export default {
27 | snippet,
28 | };
29 |
--------------------------------------------------------------------------------
/docs/components/_index.scss:
--------------------------------------------------------------------------------
1 | /// load styles required to demonstrate each component
2 | @import "box/index";
3 | @import "grid/index";
4 | @import "icon/index";
5 | @import "navigation/index";
6 | @import "panel/index";
7 | @import "tabset/index";
8 | @import "tooltip/index";
9 | @import "typography/index";
10 |
11 | /// load styles needed to test component visuals
12 | @import "checkbox/spec";
13 | @import "choice-tile/spec";
14 | @import "dropdown-select/spec";
15 | @import "email/spec";
16 | @import "file/spec";
17 | @import "menu/spec";
18 | @import "panel/spec";
19 | @import "popover/spec";
20 | @import "radio/spec";
21 | @import "textarea/spec";
22 | @import "text-input/spec";
23 | @import "password/spec";
24 |
--------------------------------------------------------------------------------
/docs/components/alert/test.html:
--------------------------------------------------------------------------------
1 | ---
2 | title: Testing - Alert
3 | crumbs:
4 | - path: components/alert
5 | label: Alert
6 | ---
7 | {% extends 'test.njk' %}
8 |
9 | {% block content %}
10 |
11 |
12 | Light DOM White Space
13 |
14 |
15 |
16 |
17 | Message with leading white space (no trailing)
18 |
19 |
20 | Message with trailing white space (no leading)
21 |
22 |
23 | Message without leading/trailing white space
24 |
25 |
26 | Long message without leading white space.
27 | It has filler text added in an attempt to get the message to wrap
28 | to multiple lines, in order to test how the status arranges itself.
29 |
30 |
31 |
32 |
33 | {% endblock %}
34 |
--------------------------------------------------------------------------------
/docs/components/badge/test.html:
--------------------------------------------------------------------------------
1 | ---
2 | title: Testing - Badge
3 | crumbs:
4 | - path: components/badge
5 | label: Badge
6 | ---
7 | {% extends 'test.njk' %}
8 |
9 | {% block content %}
10 |
24 | {% endblock %}
25 |
--------------------------------------------------------------------------------
/docs/components/box/_index.scss:
--------------------------------------------------------------------------------
1 | .box-demo {
2 | .hxBox,
3 | hx-div {
4 | border: $demo-container-border;
5 | }
6 |
7 | p {
8 | margin: 0; // FIXME
9 | }
10 |
11 | .hxXs {
12 | box-shadow: inset 0 0 0 0.5rem $demo-padding-color;
13 | }
14 |
15 | .hxSm {
16 | box-shadow: inset 0 0 0 0.75rem $demo-padding-color;
17 | }
18 |
19 | .hxMd {
20 | box-shadow: inset 0 0 0 1.25rem $demo-padding-color;
21 | }
22 |
23 | .hxLg {
24 | box-shadow: inset 0 0 0 2rem $demo-padding-color;
25 | }
26 |
27 | .hxXl {
28 | box-shadow: inset 0 0 0 3rem $demo-padding-color;
29 | }
30 |
31 | .hx2x {
32 | box-shadow: inset 0 0 0 4.5rem $demo-padding-color;
33 | }
34 | }
35 |
36 | .example > div.scroll-box-demo {
37 | overflow: hidden;
38 | padding: 0;
39 |
40 | > hx-div {
41 | height: 15rem;
42 |
43 | &[scroll="both"],
44 | &[scroll="horizontal"] {
45 | white-space: nowrap;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/docs/components/box/test.html:
--------------------------------------------------------------------------------
1 | ---
2 | title: Testing - Box
3 | crumbs:
4 | - path: components/box
5 | label: Box
6 | ---
7 | {% extends 'test.njk' %}
8 |
9 | {% block content %}
10 |
11 |
12 | Status inside Div
13 |
14 |
15 |
16 | hx-div > hx-status
17 |
18 |
19 | {% endblock %}
20 |
--------------------------------------------------------------------------------
/docs/components/button/_spec.scss:
--------------------------------------------------------------------------------
1 | @import "components/button/config";
2 |
3 | .button-spec {
4 | .hxBtn {
5 | &[class*="mock"] {
6 | pointer-events: none;
7 | }
8 |
9 | // SECONDARY
10 | &.mock-hover {
11 | @include hxButton-hover--secondary;
12 | }
13 | &.mock-active {
14 | @include hxButton-active--secondary;
15 | }
16 | &.mock-focus {
17 | @include hxButton-focus--secondary;
18 | }
19 |
20 | // PRIMARY
21 | &.hxPrimary {
22 | &.mock-hover {
23 | @include hxButton-hover--primary;
24 | }
25 | &.mock-active {
26 | @include hxButton-active--primary;
27 | }
28 | &.mock-focus {
29 | @include hxButton-focus--primary;
30 | }
31 | }
32 |
33 | // TERTIARY
34 | &.hxTertiary {
35 | &.mock-hover {
36 | @include hxButton-hover--tertiary;
37 | }
38 | &.mock-active {
39 | @include hxButton-active--tertiary;
40 | }
41 | &.mock-focus {
42 | @include hxButton-focus--tertiary;
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/docs/components/checkbox/checkbox-demo.js:
--------------------------------------------------------------------------------
1 | import Util from '../../_util';
2 |
3 | if (document.getElementById('vue-checkboxDemo')) {
4 | new Vue({
5 | el: '#vue-checkboxDemo',
6 | data: {
7 | isChecked: false,
8 | isDisabled: false,
9 | isIndeterminate: false,
10 | isRequired: false,
11 | label: 'Check me out',
12 | },
13 | computed: {
14 | snippet: function () {
15 | return Util.snippet(`
16 |
17 |
24 |
25 |
26 | ${this.label}
27 |
28 |
29 | `);
30 | },
31 | },
32 | });
33 | }
34 |
--------------------------------------------------------------------------------
/docs/components/drawer/_spec.scss:
--------------------------------------------------------------------------------
1 | .drawer-spec {
2 | .dialog-helpers {
3 | display: flex;
4 | flex-wrap: wrap;
5 | justify-content: space-between;
6 | overflow-x: visible;
7 |
8 | > * {
9 | flex-shrink: 0;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/docs/components/dropdown-select/_spec.scss:
--------------------------------------------------------------------------------
1 | @import "components/dropdown-select/config";
2 |
3 | .dropdown-select-spec {
4 | hx-select-control {
5 | /* ----- Pristine --------------- */
6 | > select.mock-focus {
7 | @include hxSelectControl($focused: true);
8 |
9 | ~ hx-select {
10 | @include hxSelectFacade($focused: true);
11 | }
12 |
13 | /* ----- Disabled --------------- */
14 | &:disabled {
15 | @include hxSelectControl(disabled, true);
16 |
17 | ~ hx-select {
18 | @include hxSelectFacade(disabled, true);
19 | }
20 | }
21 | }
22 |
23 | /* ----- Invalid ---------------*/
24 | &.hxInvalid > select.mock-focus:enabled,
25 | &[hx-dirty] > select.mock-focus:enabled:invalid {
26 | @include hxSelectControl(invalid, true);
27 |
28 | ~ hx-select {
29 | @include hxSelectFacade(invalid, true);
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/docs/components/email/_spec.scss:
--------------------------------------------------------------------------------
1 | @import "components/form/mixins/textControl";
2 |
3 | .email-input-spec {
4 | hx-email-control {
5 | /* ----- Pristine --------------- */
6 | > input[type="email"].mock-focus {
7 | @include hxTextControl($focused: true);
8 | }
9 |
10 | /* ----- Disabled --------------- */
11 | > input[type="email"]:disabled.mock-focus {
12 | @include hxTextControl(disabled, $focused: true);
13 | }
14 |
15 | /* ----- Changed / Touched --------------- */
16 | &[hx-dirty] {
17 | > input[type="email"]:invalid.mock-focus {
18 | @include hxTextControl(invalid, $focused: true);
19 | }
20 | }
21 |
22 | /* ----- Styled Invalid --------------- */
23 | &.hxInvalid > input[type="email"]:enabled.mock-focus {
24 | @include hxTextControl(invalid, $focused: true);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/docs/components/file/_spec.scss:
--------------------------------------------------------------------------------
1 | @import 'components/button/config';
2 | @import 'components/file/mixins/hxFileControl';
3 |
4 | .file-input-spec {
5 | hx-file-control {
6 | input[type="file"].mock-focus ~ label > hx-file-input {
7 | @include hxFileControl($pseudo-state: focus);
8 | }
9 |
10 | input[type="file"].mock-active ~ label > hx-file-input {
11 | &.hxBtn{
12 | @include hxButton-active--secondary;
13 | }
14 | &.hxPrimary {
15 | @include hxButton-active--primary;
16 | }
17 |
18 | &.hxTertiary {
19 | @include hxButton-active--tertiary;
20 | }
21 | }
22 |
23 | hx-file-input.hxBtn.mock-hover {
24 | @include hxButton-hover--secondary;
25 |
26 | &.hxPrimary {
27 | @include hxButton-hover--primary;
28 | }
29 |
30 | &.hxTertiary {
31 | @include hxButton-hover--tertiary;
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/docs/components/file/drop-zone-demo.js:
--------------------------------------------------------------------------------
1 | if (document.getElementById('vue-dropZoneDemo')) {
2 | new Vue({
3 | el: '#vue-dropZoneDemo',
4 | methods: {
5 | onDrop: function (evt) {
6 | if (evt.dataTransfer.items) {
7 | // Use DataTransferItemList interface to access the file(s)
8 | Array.from(evt.dataTransfer.items).forEach(item => {
9 | // If dropped items aren't files, reject them
10 | if (item.kind === 'file') {
11 | let file = item.getAsFile();
12 | alert('File Drop Successful! ' + file.name);
13 | }
14 | });
15 | } else {
16 | // TODO: find solution, unsure how to pull file info in IE11
17 | alert('We detected a file drop!');
18 | }
19 | },
20 | },
21 | });
22 | }
23 |
--------------------------------------------------------------------------------
/docs/components/icon/_index.scss:
--------------------------------------------------------------------------------
1 | .icon-media {
2 | background-color: $gray-0;
3 | border: 1px solid $gray-400;
4 | height: 100%;
5 | padding: 1.25rem;
6 |
7 | .media__icon {
8 | color: $gray-1000;
9 | display: flex;
10 | font-size: 2em;
11 | line-height: 1;
12 | }
13 |
14 | .media__body {
15 | margin-left: 1.25rem;
16 | }
17 | }
18 |
19 | hx-icon {
20 | &.size-2x {
21 | height: 2em;
22 | width: 2em;
23 | }
24 |
25 | &.size-3x {
26 | height: 3em;
27 | width: 3em;
28 | }
29 |
30 | &.danger {
31 | color: $red-status-500;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/docs/components/index.js:
--------------------------------------------------------------------------------
1 | /* import/load JS needed for each component demo/docs */
2 | // TBD
3 |
--------------------------------------------------------------------------------
/docs/components/list/list-demo.js:
--------------------------------------------------------------------------------
1 | if (document.getElementById('vue-listDemo')) {
2 | new Vue({
3 | el: '#vue-listDemo',
4 | data: {
5 | isVertical: false,
6 | },
7 | computed: {
8 | classes: function () {
9 | let out = [ 'hxList' ];
10 | if (this.isVertical) {
11 | out.push('hxVertical');
12 | }
13 | return out.join(' ');
14 | },
15 | },
16 | });
17 | }
18 |
--------------------------------------------------------------------------------
/docs/components/loader/loader-demo.js:
--------------------------------------------------------------------------------
1 | import Util from '../../_util';
2 |
3 | if (document.getElementById('vue-busyDemo')) {
4 | new Vue({
5 | el: '#vue-busyDemo',
6 | data: {
7 | isPaused: false,
8 | },
9 | });
10 | }
11 |
12 | if (document.getElementById('vue-progressDemo')) {
13 | new Vue({
14 | el: '#vue-progressDemo',
15 | data: {
16 | pct: 42,
17 | },
18 | computed: {
19 | snippet: function () {
20 | return Util.snippet(`
21 |
22 | `);
23 | },
24 | },
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/docs/components/menu/_spec.scss:
--------------------------------------------------------------------------------
1 | .menu-positioning-spec {
2 | [id^="target"] {
3 | align-items: center;
4 | background-color: $gray-300;
5 | display: flex;
6 | height: 6rem;
7 | justify-content: center;
8 | position: fixed;
9 | width: 6rem;
10 | }
11 |
12 | // vertical target alignment
13 | [id$="quad1"],
14 | [id$="quad4"] {
15 | top: 33%;
16 | }
17 |
18 | [id$="quad2"],
19 | [id$="quad3"] {
20 | top: 67%;
21 | }
22 |
23 | // horizontal target alignment
24 | [id$="quad1"],
25 | [id$="quad2"] {
26 | left: 67%;
27 | }
28 |
29 | [id$="quad3"],
30 | [id$="quad4"] {
31 | left: 33%;
32 | }
33 |
34 | #target-center,
35 | #target-quad1,
36 | #target-quad2,
37 | #target-quad3,
38 | #target-quad4 {
39 | transform: translate(-50%, -50%);
40 | }
41 |
42 | #target-center {
43 | height: 9rem;
44 | left: 50%;
45 | top: 50%;
46 | width: 9rem;
47 | }
48 |
49 | #target-topLeft {
50 | left: 0;
51 | top: 0;
52 | }
53 |
54 | #target-topRight {
55 | right: 0;
56 | top: 0;
57 | }
58 |
59 | #target-bottomLeft {
60 | bottom: 0;
61 | left: 0;
62 | }
63 |
64 | #target-bottomRight {
65 | bottom: 0;
66 | right: 0;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/docs/components/menu/test.html:
--------------------------------------------------------------------------------
1 | ---
2 | title: Testing - Menu
3 | crumbs:
4 | - path: components/menu
5 | label: Menu
6 | ---
7 | {% extends 'test.njk' %}
8 |
9 | {% block content %}
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 | Table Header
20 |
21 |
22 |
23 |
28 |
29 |
30 |
31 |
32 |
33 | {% endblock %}
34 |
--------------------------------------------------------------------------------
/docs/components/navigation/_index.scss:
--------------------------------------------------------------------------------
1 | .nav-demo {
2 | .hxNav {
3 | width: $app-nav-width;
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/docs/components/panel/_index.scss:
--------------------------------------------------------------------------------
1 | .docs-panel {
2 | #demo-basic {
3 | height: 15rem;
4 | max-height: 20rem;
5 | min-height: 10rem;
6 |
7 | .hxPanel {
8 | border: $demo-container-border;
9 |
10 | > header {
11 | border-bottom: $demo-container-border;
12 | }
13 |
14 | > footer {
15 | border-top: $demo-container-border;
16 | }
17 | }
18 | }
19 |
20 | #demo-tabbed {
21 | height: 20rem;
22 | max-height: 30rem;
23 | min-height: 20rem;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/docs/components/panel/_spec.scss:
--------------------------------------------------------------------------------
1 | .specs-panel {
2 |
3 | .spec {
4 | &.scroll {
5 | height: 20rem;
6 | overflow: hidden;
7 | }
8 |
9 | &.visible {
10 | /* Visualize Invisible Panel Boundaries */
11 | hx-panel, // DEPRECATED: remove in v1.0.0
12 | .hxPanel {
13 | border: $demo-container-border;
14 |
15 | > hx-panelhead, // DEPRECATED: remove in v1.0.0
16 | > header {
17 | border-bottom: $demo-container-border;
18 | }
19 |
20 | > hx-panelfoot, // DEPRECATED: remove in v1.0.0
21 | > footer {
22 | border-top: $demo-container-border;
23 | }
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/docs/components/panel/panel-demo.js:
--------------------------------------------------------------------------------
1 | if (document.getElementById('vue-panelDemo')) {
2 | new Vue({
3 | el: '#vue-panelDemo',
4 | data: {
5 | hasHeader: true,
6 | hasFooter: true,
7 | },
8 | });
9 | }
10 |
--------------------------------------------------------------------------------
/docs/components/password/_spec.scss:
--------------------------------------------------------------------------------
1 | @import "components/form/mixins/textControl";
2 |
3 | .password-spec {
4 | hx-password-control {
5 | // ----- Pristine ---------------
6 | > input[type="password"].mock-focus {
7 | @include hxTextControl($focused: true);
8 | }
9 |
10 | // ----- Disabled ---------------
11 | > input[type="password"]:disabled.mock-focus {
12 | @include hxTextControl(disabled, $focused: true);
13 | }
14 |
15 | // ----- Changed / Touched ---------------
16 | &[hx-dirty] {
17 | > input[type="password"]:invalid.mock-focus {
18 | @include hxTextControl(invalid, $focused: true);
19 | }
20 | }
21 |
22 | // ----- Styled Invalid ---------------
23 | &.hxInvalid > input[type="password"]:enabled.mock-focus {
24 | @include hxTextControl(invalid, $focused: true);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/docs/components/pill/test.html:
--------------------------------------------------------------------------------
1 | ---
2 | title: Testing - Pill
3 | crumbs:
4 | - path: components/pill
5 | label: Pill
6 | ---
7 | {% extends 'test.njk' %}
8 |
9 | {% block content %}
10 |
11 | Outside Tables
12 |
13 | Persistent
14 | Dismissible
15 |
16 |
17 |
18 |
19 | Inside Tables
20 |
21 |
22 |
23 |
24 | Persistent
25 |
26 |
27 |
28 |
29 | Dismissable
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | Inside Tables (Condensed)
38 |
39 |
40 |
41 |
42 | Persistent
43 |
44 |
45 |
46 |
47 | Dismissable
48 |
49 |
50 |
51 |
52 |
53 | {% endblock %}
54 |
--------------------------------------------------------------------------------
/docs/components/popover/_spec.scss:
--------------------------------------------------------------------------------
1 | .popover-spec {
2 | #popover-in-scrolling-container {
3 | hx-div[scroll="vertical"] {
4 | border: 1px solid;
5 | height: 15rem; // 240px
6 | width: 30rem; // 480px
7 | }
8 | }
9 |
10 | .popover-appearance {
11 | display: flex;
12 | flex-wrap: wrap;
13 | z-index: 0;
14 |
15 | hx-popover {
16 | display: block;
17 | margin: 20px;
18 | position: relative;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/docs/components/popover/popover-demo.js:
--------------------------------------------------------------------------------
1 | import { WITH_ARROW as POSITIONS } from '../../_positions.js';
2 |
3 | if (document.getElementById('vue-popoverDemo')) {
4 | new Vue({
5 | el: '#vue-popoverDemo',
6 | data: {
7 | position: POSITIONS[6], // "bottom-right"
8 | positions: POSITIONS,
9 | },
10 | });
11 | }
12 |
13 | if (document.getElementById('vue-scrollingPopoverDemo')) {
14 | new Vue({
15 | el: '#vue-scrollingPopoverDemo',
16 | data: {
17 | position: POSITIONS[6], // "bottom-right"
18 | positions: POSITIONS,
19 | },
20 | });
21 | }
22 |
--------------------------------------------------------------------------------
/docs/components/radio/radio-basic-demo.js:
--------------------------------------------------------------------------------
1 | import Util from '../../_util';
2 |
3 | if (document.getElementById('vue-radioBasicDemo')) {
4 | new Vue({
5 | el: '#vue-radioBasicDemo',
6 | data: {
7 | isChecked: false,
8 | isDisabled: false,
9 | isRequired: false,
10 | radioLabel: 'Radio Label',
11 | },
12 | computed: {
13 | snippet: function () {
14 | return Util.snippet(`
15 |
16 |
23 |
24 |
25 | ${this.radioLabel}
26 |
27 |
28 | `);
29 | },
30 | },
31 | });
32 | }
33 |
--------------------------------------------------------------------------------
/docs/components/reveal/reveal-demo.js:
--------------------------------------------------------------------------------
1 | if (document.getElementById('vue-revealDemo')) {
2 | new Vue({
3 | el: '#vue-revealDemo',
4 | data: {
5 | isDisabled: false,
6 | },
7 | });
8 | }
9 |
--------------------------------------------------------------------------------
/docs/components/stepper/stepper-demo.js:
--------------------------------------------------------------------------------
1 | if (document.getElementById('vue-stepperDemo')) {
2 | new Vue({
3 | el: '#vue-stepperDemo',
4 | data: {},
5 | methods: {
6 | nextStep: function () {
7 | this.$refs.accordion.selectNext();
8 | },
9 | prevStep: function () {
10 | this.$refs.accordion.selectPrevious();
11 | },
12 | },
13 | });
14 | }
15 |
--------------------------------------------------------------------------------
/docs/components/switch/_spec.scss:
--------------------------------------------------------------------------------
1 | @import "components/switch/config";
2 |
3 | // TBD
4 |
--------------------------------------------------------------------------------
/docs/components/switch/error-switch-demo.js:
--------------------------------------------------------------------------------
1 | import Util from '../../_util';
2 |
3 | if (document.getElementById('vue-switchErrorDemo')) {
4 | new Vue({
5 | el: '#vue-switchErrorDemo',
6 | data: {
7 | isInValid: false,
8 | labelState: '',
9 | option : 'ON',
10 | },
11 | computed: {
12 | attrInValid: function () {
13 | return (this.isInValid ? 'invalid' : '');
14 | },
15 | snippet: function () {
16 | return Util.snippet(`
17 |
18 |
21 |
22 |
26 |
27 |
28 |
29 | `);
30 | },
31 | },
32 | });
33 | }
34 |
--------------------------------------------------------------------------------
/docs/components/switch/test.html:
--------------------------------------------------------------------------------
1 | ---
2 | title: Testing - Switch
3 | crumbs:
4 | - path: components/switch
5 | label: Switch
6 | ---
7 | {% extends 'test.njk' %}
8 |
9 | {% block content %}
10 | {# TODO: Add visual/interactive tests #}
11 | {% endblock %}
12 |
--------------------------------------------------------------------------------
/docs/components/table/table-demo.js:
--------------------------------------------------------------------------------
1 | if (document.getElementById('vue-tableDemo')) {
2 | new Vue({
3 | el: '#vue-tableDemo',
4 | data: {
5 | isBound: false,
6 | isHoverable: false,
7 | isCondensed: false,
8 | },
9 | computed: {
10 | cssClasses: function () {
11 | var out = [ 'hxTable' ];
12 | if (this.isCondensed) {
13 | out.push('hxTable--condensed');
14 | }
15 | if (this.isBound) {
16 | out.push('hxBound');
17 | }
18 | if (this.isHoverable) {
19 | out.push('hxHoverable');
20 | }
21 | return out.join(' ');
22 | },
23 | },
24 | });
25 | }
26 |
--------------------------------------------------------------------------------
/docs/components/tabset/_index.scss:
--------------------------------------------------------------------------------
1 | .docs-tabset {
2 | #demo-basic {
3 | height: 22rem;
4 | max-height: 40rem;
5 | min-height: 22rem;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/docs/components/text-input/_spec.scss:
--------------------------------------------------------------------------------
1 | @import "components/form/mixins/textControl";
2 |
3 | .text-input-spec {
4 | hx-text-control {
5 | /* ----- Pristine --------------- */
6 | > input[type="text"].mock-focus {
7 | @include hxTextControl($focused: true);
8 | }
9 |
10 | /* ----- Disabled --------------- */
11 | > input[type="text"]:disabled.mock-focus {
12 | @include hxTextControl(disabled, $focused: true);
13 | }
14 |
15 | /* ----- Changed / Touched --------------- */
16 | &[hx-dirty] {
17 | > input[type="text"]:invalid.mock-focus {
18 | @include hxTextControl(invalid, $focused: true);
19 | }
20 | }
21 |
22 | /* ----- Styled Invalid --------------- */
23 | &.hxInvalid > input[type="text"]:enabled.mock-focus {
24 | @include hxTextControl(invalid, $focused: true);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/docs/components/textarea/_spec.scss:
--------------------------------------------------------------------------------
1 | @import "components/form/mixins/textControl";
2 |
3 | .textarea-spec {
4 | hx-textarea-control {
5 | // ----- Pristine ---------------
6 | > textarea.mock-focus {
7 | @include hxTextControl($focused: true);
8 | }
9 |
10 | // ----- Disabled ---------------
11 | > textarea:disabled.mock-focus {
12 | @include hxTextControl(disabled, $focused: true);
13 | }
14 |
15 | // ----- Changed / Touched ---------------
16 | &[hx-dirty] {
17 | > textarea:invalid.mock-focus {
18 | @include hxTextControl(invalid, $focused: true);
19 | }
20 | }
21 |
22 | // ----- Styled Invalid ---------------
23 | &.hxInvalid > textarea:enabled.mock-focus {
24 | @include hxTextControl(invalid, $focused: true);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/docs/components/toggle/_spec.scss:
--------------------------------------------------------------------------------
1 | @import "components/toggle/config";
2 |
3 | // TBD
4 |
--------------------------------------------------------------------------------
/docs/components/toggle/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title: Toggle
3 | minver: 1.0.0
4 | also:
5 | elements/hx-toggle:
6 | elements/hx-toggle-control:
7 | ---
8 | {% extends 'component.njk' %}
9 |
10 | {% block page_header %}
11 |
12 | A {{page.title}} controls the presentation format (list || grid) for
13 | information on a control panel page.
14 |
15 | {% endblock %}
16 |
17 | {% block content %}
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
36 |
37 |
38 | {% endblock %}
39 |
--------------------------------------------------------------------------------
/docs/components/toggle/test.html:
--------------------------------------------------------------------------------
1 | ---
2 | title: Testing - Toggle
3 | crumbs:
4 | - path: components/toggle
5 | label: Toggle
6 | ---
7 | {% extends 'test.njk' %}
8 |
9 | {% block content %}
10 | {# TODO: Add visual/interactive tests #}
11 | {% endblock %}
12 |
--------------------------------------------------------------------------------
/docs/components/toggle/toggle-demo.js:
--------------------------------------------------------------------------------
1 | import Util from '../../_util';
2 |
3 | if (document.getElementById('vue-toggleDemo')) {
4 | new Vue({
5 | el: '#vue-toggleDemo',
6 | computed: {
7 | snippet: function () {
8 | return Util.snippet(`
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | `);
17 | },
18 | },
19 | });
20 | }
21 |
--------------------------------------------------------------------------------
/docs/components/tooltip/_index.scss:
--------------------------------------------------------------------------------
1 | .tooltip-appearance {
2 | display: flex;
3 | flex-wrap: wrap;
4 | z-index: 0;
5 |
6 | > hx-tooltip {
7 | margin: 1.25rem;
8 | position: relative;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/docs/components/tooltip/tooltip-demo.js:
--------------------------------------------------------------------------------
1 | import { WITH_ARROW as POSITIONS } from '../../_positions.js';
2 |
3 | if (document.getElementById('vue-tooltipDemo')) {
4 | new Vue({
5 | el: '#vue-tooltipDemo',
6 | data: {
7 | position: POSITIONS[1], // "top-center"
8 | positions: POSITIONS,
9 | },
10 | });
11 | }
12 |
--------------------------------------------------------------------------------
/docs/components/typography/_index.scss:
--------------------------------------------------------------------------------
1 | @import "base/links";
2 |
3 | .demo-typography {
4 | .font-open-sans {
5 | font-family: "Open Sans", "Roboto", sans-serif;
6 | }
7 |
8 | .font-open-sans-condensed {
9 | font-family: "Open Sans Condensed", "Roboto Mono", monospace;
10 | }
11 |
12 | .weight-thin { font-weight: 100; }
13 | .weight-light { font-weight: 300; }
14 | .weight-regular { font-weight: 400; }
15 | .weight-medium { font-weight: 500; }
16 | .weight-bold { font-weight: 700; }
17 | }
18 |
19 | a {
20 | &.pseudo-active {
21 | @extend a[href]:active;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/docs/elements/hx-checkbox/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 0.16.0
4 | also:
5 | components/checkbox: Checkbox
6 | elements/hx-checkbox-control:
7 | ---
8 | {% extends 'element.njk' %}
9 | {% block page_header %}
10 |
11 | The {{page.title}}
inline element is a stylistic facade used
12 | to build a Checkbox component.
13 |
14 | {% endblock %}
15 |
16 | {% block content %}
17 |
18 |
19 |
20 |
Permitted Parents
21 | any element that accepts flow content
22 |
23 |
24 |
Permitted Children
25 | none
26 |
27 |
28 |
Events
29 | none
30 |
31 |
32 |
33 | {% endblock %}
34 |
--------------------------------------------------------------------------------
/docs/elements/hx-drop-fence/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 0.14.0
4 | also:
5 | components/file: File
6 | ---
7 | {% extends 'element.njk' %}
8 | {% block page_header %}
9 |
10 | The custom {{page.title}}
element provides a visual
11 | indication to the user that they can drag a file into an area.
12 |
13 | {% endblock %}
14 |
15 | {% block content %}
16 |
17 |
18 |
19 |
Display
20 | block
21 |
22 |
23 |
Permitted Parents
24 | any
25 |
26 |
27 |
Permitted Children
28 | flow content
29 |
30 |
31 |
Events
32 | none
33 |
34 |
35 |
36 | {% endblock %}
37 |
38 |
--------------------------------------------------------------------------------
/docs/elements/hx-error/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 0.4.0
4 | also:
5 | components/Typography: Typography
6 | ---
7 | {% extends 'element.njk' %}
8 | {% block page_header %}
9 |
10 | The custom {{page.title}}
element provides an informative
11 | icon and applies styling to communicate an error message to users.
12 |
13 | {% endblock %}
14 |
15 | {% block content %}
16 |
17 |
18 |
19 |
Permitted Parents
20 | Any that accept Phrasing Content
21 |
22 |
23 |
Permitted Children
24 | Phrasing Content
25 |
26 |
27 |
Events
28 | none
29 |
30 |
31 |
32 | {% endblock %}
33 |
34 |
--------------------------------------------------------------------------------
/docs/elements/hx-icon/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 0.1.0
4 | also:
5 | components/icon: Icon
6 | elements/hx-file-icon:
7 | ---
8 | {% extends 'element.njk' %}
9 | {% block page_header %}
10 |
11 | The custom {{page.title}}
element renders one of many
12 | built-in SVG icons.
13 |
14 | {% endblock %}
15 |
16 | {% block content %}
17 |
18 |
19 |
20 |
Permitted Parents
21 | any element that accepts embedded content
22 |
23 |
24 |
Permitted Children
25 | none
26 |
27 |
28 |
Events
29 | none
30 |
31 |
32 |
33 | {% endblock %}
34 |
35 | {% block attributes %}
36 |
37 | type {String}
38 |
39 | Changes the displayed icon to one of the
40 | available icons
41 |
42 |
43 | {% endblock %}
44 |
--------------------------------------------------------------------------------
/docs/elements/hx-menuitem/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 0.2.0
4 | also:
5 | components/menu: Menu
6 | elements/hx-menu:
7 | ---
8 | {% extends 'element.njk' %}
9 | {% block page_header %}
10 |
11 | The custom {{page.title}}
element represents an action
12 | or function that a user can initiate.
13 |
14 | {% endblock %}
15 |
16 | {% block content %}
17 |
18 |
19 |
20 |
Permitted Parents
21 |
22 | either of the following:
23 |
24 | an <hx-menu> element
25 | a <section>
element
26 |
27 |
28 |
29 |
30 |
Permitted Children
31 | flow content
32 |
33 |
34 |
Events
35 | none
36 |
37 |
38 |
39 | {% endblock %}
40 |
--------------------------------------------------------------------------------
/docs/elements/hx-radio/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 0.16.0
4 | also:
5 | components/radio: Radio
6 | elements/hx-radio-control:
7 | elements/hx-radio-set:
8 | ---
9 | {% extends 'element.njk' %}
10 | {% block page_header %}
11 |
12 | The {{page.title}}
inline element is a stylistic facade used
13 | to build a Radio component.
14 |
15 | {% endblock %}
16 |
17 | {% block content %}
18 |
19 |
20 |
21 |
Permitted Parents
22 | any element that accepts flow content
23 |
24 |
25 |
Permitted Children
26 | none
27 |
28 |
29 |
Events
30 | none
31 |
32 |
33 |
34 | {% endblock %}
35 |
--------------------------------------------------------------------------------
/docs/elements/hx-search/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 0.18.0
4 | also:
5 | components/search: Search
6 | elements/hx-search-control:
7 | ---
8 | {% extends 'element.njk' %}
9 | {% import '_utils.njk' as utils %}
10 | {% block page_header %}
11 |
12 | The {{page.title}}
inline element is a stylistic facade
13 | used to build a Search component.
14 |
15 | {% endblock %}
16 |
17 | {% block content %}
18 |
19 |
20 |
21 |
Permitted Parents
22 | {{ utils.customElement('hx-search-control') }}
23 |
24 |
25 |
Permitted Children
26 | none
27 |
28 |
29 |
Events
30 | none
31 |
32 |
33 |
34 | {% endblock %}
35 |
--------------------------------------------------------------------------------
/docs/elements/hx-select/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 0.16.0
4 | also:
5 | components/dropdown-select: Dropdown Select
6 | elements/hx-select-control:
7 | ---
8 | {% extends 'element.njk' %}
9 | {% import '_utils.njk' as utils %}
10 | {% block page_header %}
11 |
12 | The {{page.title}}
block element is a stylistic facade used
13 | to build a Dropdown Select component.
14 |
15 | {% endblock %}
16 |
17 | {% block content %}
18 |
19 |
20 |
21 |
Permitted Parents
22 | {{utils.customElement('hx-select-control')}}
23 |
24 |
25 |
Permitted Children
26 | none
27 |
28 |
29 |
Events
30 | none
31 |
32 |
33 |
34 | {% endblock %}
35 |
--------------------------------------------------------------------------------
/docs/elements/hx-status/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 0.2.0
4 | also:
5 | components/pill: Pill
6 | ---
7 | {% extends 'element.njk' %}
8 | {% block page_header %}
9 | {# TODO: add element description #}
10 | {% endblock %}
11 |
12 | {% block content %}
13 |
14 |
15 |
16 |
Permitted Parents
17 | any
18 |
19 |
20 |
Permitted Children
21 | flow content
22 |
23 |
24 |
Events
25 | none
26 |
27 |
28 |
29 | {% endblock %}
30 |
--------------------------------------------------------------------------------
/docs/elements/hx-switch/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 0.24.0
4 | also:
5 | components/switch: Switch
6 | elements/hx-switch-control:
7 | ---
8 | {% extends 'element.njk' %}
9 | {% import '_utils.njk' as utils %}
10 | {% block page_header %}
11 |
12 | The {{page.title}}
enables the user to make a binary decision
13 | (such as yes or no, and on or off) when configuring a setting or preference.
14 | It is used to build a Switch component.
15 |
16 | {% endblock %}
17 |
18 | {% block content %}
19 |
20 |
21 |
22 |
Permitted Grandparent
23 | {{utils.element('hx-switch-control')}} element
24 |
25 |
26 |
Permitted Parent
27 | {{utils.element('label')}} (wrapper) element
28 |
29 |
30 |
Permitted Children
31 | none
32 |
33 |
34 |
Events
35 | none
36 |
37 |
38 |
39 | {% endblock %}
40 |
41 | {% block attributes %}
42 | {% endblock %}
43 |
44 | {% block properties %}
45 | {% endblock %}
46 |
--------------------------------------------------------------------------------
/docs/elements/hx-tile/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 0.4.0
4 | also:
5 | components/choice-tile: Choice Tile
6 | ---
7 | {% extends 'element.njk' %}
8 | {% block page_header %}
9 |
10 | The custom {{page.title}}
element is compromised of an icon,
11 | label, and optional description.
12 |
13 | {% endblock %}
14 |
15 | {% block content %}
16 |
17 |
18 |
19 |
Permitted Parents
20 | any
21 |
22 |
23 |
Permitted Children
24 |
25 | in this order:
26 |
27 | a required checkmark <hx-icon> element
28 | a required div.hx-tile-icon
wrapping icon of choice
29 | a required <header>
element with the tile label
30 | an optional <p>
element with the tile description
31 |
32 |
33 |
34 |
35 |
Events
36 | none
37 |
38 |
39 |
40 | {% endblock %}
41 |
--------------------------------------------------------------------------------
/docs/elements/hx-toggle/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | minver: 1.0.0
4 | also:
5 | components/toggle: Toggle
6 | elements/hx-toggle-control:
7 | ---
8 | {% extends 'element.njk' %}
9 | {% import '_utils.njk' as utils %}
10 | {% block page_header %}
11 |
12 | The {{page.title}}
controls the presentation format
13 | for information on a control panel page. It is used to build
14 | a Toggle component.
15 |
16 | {% endblock %}
17 |
18 | {% block content %}
19 |
20 |
21 |
22 |
Permitted Grandparent
23 | {{utils.element('hx-toggle-control')}} element
24 |
25 |
26 |
Permitted Parent
27 | {{utils.element('label')}} (wrapper) element
28 |
29 |
30 |
Permitted Children
31 | none
32 |
33 |
34 |
Events
35 | none
36 |
37 |
38 |
39 | {% endblock %}
40 |
41 | {% block attributes %}
42 | {% endblock %}
43 |
44 | {% block properties %}
45 | {% endblock %}
46 |
--------------------------------------------------------------------------------
/docs/files/easteregg.txt:
--------------------------------------------------------------------------------
1 | # CONGRATULATIONS!
2 |
3 | You've found the secret file!
4 |
--------------------------------------------------------------------------------
/docs/images/200x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelixDesignSystem/helix-ui/82967eda7ee1542c54312a9c127c262256ad7b3c/docs/images/200x150.png
--------------------------------------------------------------------------------
/docs/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelixDesignSystem/helix-ui/82967eda7ee1542c54312a9c127c262256ad7b3c/docs/images/favicon.png
--------------------------------------------------------------------------------
/docs/images/thumbs/horizontal-layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelixDesignSystem/helix-ui/82967eda7ee1542c54312a9c127c262256ad7b3c/docs/images/thumbs/horizontal-layout.png
--------------------------------------------------------------------------------
/docs/images/thumbs/vertical-layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelixDesignSystem/helix-ui/82967eda7ee1542c54312a9c127c262256ad7b3c/docs/images/thumbs/vertical-layout.png
--------------------------------------------------------------------------------
/docs/index.scss:
--------------------------------------------------------------------------------
1 | @import "vars";
2 | @import "components/grid/_config.scss";
3 | @import "components/box/_config.scss";
4 |
5 | // DOCS VARS
6 | $demo-container-border: 1px dashed $gray-600;
7 | $demo-fill-color: rgba($orange-500, 0.25);
8 | $demo-padding-color: $magenta-100;
9 |
10 | @mixin supports-grid {
11 | @supports (display: grid) {
12 | @content;
13 | }
14 | }
15 |
16 | // element metadata container
17 | .metadata {
18 | @include box-size(md);
19 | background-color: $cyan-50;
20 | border: 1px solid $cyan-100;
21 | box-shadow: inset 0.5rem 0 0 0 $cyan-100;
22 |
23 | dt {
24 | @include grid-span(3);
25 | }
26 |
27 | dd {
28 | @include grid-span(9);
29 | }
30 | }
31 |
32 | // BASE
33 | @import "./layout";
34 | @import "./test-content";
35 |
36 | // COMPONENTS
37 | @import "./banner";
38 | @import "./example";
39 | @import "./toc";
40 |
41 | // Component-specific Doc Styles
42 | @import "./components/index";
43 |
44 | // Spec Styles for component test pages
45 | @import "./components/drawer/spec";
46 | @import "./components/search/spec";
47 | @import "./components/button/spec";
48 |
49 | // BETA
50 | @import "./darkButtons";
51 |
52 | // OVERRIDES
53 | @import "./shame";
54 |
--------------------------------------------------------------------------------
/docs/scripts/test-helpers.js:
--------------------------------------------------------------------------------
1 | // Add [data-mock-invalid] to elements in test pages to force :invalid state.
2 | // Only works on elements with the `setCustomValidity(msg)` method.
3 | (function () {
4 | let allMockInvalid = document.querySelectorAll('[data-mock-invalid]');
5 | let mockInvalidElements = Array.from(allMockInvalid);
6 |
7 | mockInvalidElements.forEach(function (el) {
8 | if (el.setCustomValidity) {
9 | el.setCustomValidity('invalid for testing');
10 | }
11 | });
12 | })();
13 |
14 | // Add [data-mock-indeterminate] to elements in test pagest ot force :indeterminate state
15 | (function () {
16 | let allMockIndeterminate = document.querySelectorAll('[data-mock-indeterminate]');
17 | let mockIndeterminateElements = Array.from(allMockIndeterminate);
18 |
19 | mockIndeterminateElements.forEach(function (el) {
20 | el.indeterminate = true;
21 | });
22 | })();
23 |
--------------------------------------------------------------------------------
/docs/vendor/custom-elements-es5-adapter.js:
--------------------------------------------------------------------------------
1 | /**
2 | @license @nocompile
3 | Copyright (c) 2018 The Polymer Project Authors. All rights reserved.
4 | This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5 | The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 | The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7 | Code distributed by Google as part of the polymer project is also
8 | subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
9 | */
10 | (function () {
11 | 'use strict';
12 |
13 | (function(){if(void 0===window.Reflect||void 0===window.customElements||window.customElements.hasOwnProperty('polyfillWrapFlushCallback'))return;const a=HTMLElement;window.HTMLElement=function(){return Reflect.construct(a,[],this.constructor)},HTMLElement.prototype=a.prototype,HTMLElement.prototype.constructor=HTMLElement,Object.setPrototypeOf(HTMLElement,a);})();
14 |
15 | }());
16 |
--------------------------------------------------------------------------------
/git-hooks/commit/index.js:
--------------------------------------------------------------------------------
1 | const TYPES = require('./types');
2 | const Err = require('./errors');
3 |
4 | module.exports = {
5 | Err,
6 | TYPES,
7 | };
8 |
--------------------------------------------------------------------------------
/git-hooks/commit/types.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'build': 'update/modify build system and/or dependencies',
3 | 'chore': 'any change that does not fit into any other type',
4 | 'docs': 'changes to documentation content',
5 | 'feat': 'add new functionality (semver MINOR)',
6 | 'fix': 'patch bug/error (semver PATCH)',
7 | 'perf': 'code changes that improve performance',
8 | 'publish': 'reserved for pipeline processes',
9 | 'refactor': 'code changes that neither fix a bug nor add a feature',
10 | 'saas': 'changes to SAAS configurations',
11 | 'style': 'code changes that do not modify algorithms (white space, linting, etc.)',
12 | 'test': 'add missing tests or update existing tests',
13 | };
14 |
--------------------------------------------------------------------------------
/git-hooks/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Check for linting errors
4 | echo "[pre-commit] check linting"
5 | npm run lint
6 |
--------------------------------------------------------------------------------
/gulpfile.esm.js:
--------------------------------------------------------------------------------
1 | export * from './tasks';
2 | export { bundle as default } from './tasks';
3 |
--------------------------------------------------------------------------------
/jsdoc.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "opts": {
3 | "recurse": true,
4 | "destination": "./public/api"
5 | },
6 | "source": {
7 | "include": [
8 | "src"
9 | ]
10 | },
11 | "markdown": {
12 | "idInHeadings": true
13 | },
14 | "plugins": [
15 | "plugins/markdown"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/karma-init.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @overview Karma start script.
3 | *
4 | * Used to initialize HelixUI ES Modules for testing.
5 | */
6 |
7 | import HelixUI from './dist/js/helix-ui.module.js';
8 |
9 | HelixUI.initialize();
10 |
--------------------------------------------------------------------------------
/karma-sauce-init.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @overview Karma SauceLabs start up script.
3 | *
4 | * Used to initialize minified HelixUI ES Modules for testing.
5 | */
6 |
7 | import HelixUI from './dist/js/helix-ui.module.min.js';
8 |
9 | HelixUI.initialize();
10 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | [[redirects]]
2 | from = "/helix-ui/*"
3 | to = "/:splat"
4 |
--------------------------------------------------------------------------------
/scripts/_config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const CONFIG = {};
5 |
6 | /* ===== PATHS ===== */
7 | // absolute path to project directory
8 | CONFIG.root = path.resolve(__dirname, '../../');
9 | CONFIG.publicDir = 'public';
10 | CONFIG.sourceDir = 'src';
11 | CONFIG.docsDir = 'docs';
12 | CONFIG.testDir = 'test';
13 | CONFIG.distDir = 'dist';
14 | CONFIG.tmpDir = '_tmp';
15 |
16 | // Component Explorer configuration
17 | // Used directly for "site" rendering context
18 | CONFIG.site = {
19 | title: 'HelixUI',
20 | language: 'en',
21 | baseHref: '/helix-ui/',
22 | // Moment.js format string
23 | dateFormat: 'YYYY-MM-DD',
24 | // Moment.js format string
25 | timeFormat: 'HH:mm:ss',
26 | };
27 |
28 | // Configuration for the LESS precompiler
29 | CONFIG.less = {
30 | paths: [
31 | `${CONFIG.docsDir}/styles`,
32 | `${CONFIG.sourceDir}/less`
33 | ],
34 | };
35 |
36 | CONFIG.sass = {
37 | includePaths: [
38 | `${CONFIG.sourceDir}/scss`
39 | ],
40 | precision: 4,
41 | }
42 |
43 | /* Define Exports */
44 | module.exports = CONFIG;
45 |
--------------------------------------------------------------------------------
/scripts/_generate/nunjucks.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const nunjucks = require('nunjucks');
4 |
5 | const CONFIG = require('../_config');
6 |
7 | const njkSrcDir = `${CONFIG.root}/${CONFIG.docsDir}/_nunjucks`;
8 |
9 | const envConfig = {
10 | autoescape: true,
11 | trimBlocks: true,
12 | lstripBlocks: true,
13 | noCache: true,
14 | };
15 |
16 | const loaders = [
17 | new nunjucks.FileSystemLoader(`${CONFIG.docsDir}/_templates`)
18 | ];
19 |
20 | const env = new nunjucks.Environment(loaders, envConfig);
21 |
22 | // See https://mozilla.github.io/nunjucks/api.html#custom-filters
23 | env.addFilter('toc', require(`${njkSrcDir}/toc.filter`));
24 |
25 | // See https://mozilla.github.io/nunjucks/api.html#custom-tags
26 | env.addExtension('CodeTag', require(`${njkSrcDir}/code.tag`));
27 |
28 | module.exports = env;
29 |
--------------------------------------------------------------------------------
/scripts/_publish/publishDocs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /*
4 | * Tasks in this file handle pushing assets to remote servers
5 | * for user consumption.
6 | */
7 | const ghPages = require('gh-pages');
8 | const moment = require('moment');
9 |
10 | const PKG = require('../../package.json');
11 | const CONFIG = require('../_config');
12 |
13 | // Pushes public/ to github pages
14 | async function publishDocs () {
15 | console.log('DOCS: Publishing to GitHub Pages'); // See https://github.com/tschaub/gh-pages#options
16 | let cfg = {
17 | add: false, // replace all gh-pages content, do not append
18 | dotfiles: false,
19 | message: `publish(docs): v${PKG.version} (${moment().format('YYYY-MM-DD HH:mm:ss')})`,
20 | remote: 'upstream',
21 | silent: false,
22 | };
23 |
24 | try {
25 | await ghPages.publish(CONFIG.publicDir, cfg);
26 | console.log('Successfully published!');
27 | } catch (err) {
28 | console.log(`ERROR publishing: ${err.message}`);
29 | }
30 | }//publishDocs
31 |
32 | exports.publishDocs = publishDocs;
33 |
--------------------------------------------------------------------------------
/scripts/_util/copy.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /*
4 | * Tasks in this file handle copying files or directories to public/
5 | */
6 |
7 | const { ensureDir, copy } = require('fs-extra');
8 |
9 | const CONFIG = require('../_config');
10 |
11 | async function copyDist () {
12 | let sourcePath = `${CONFIG.root}/${CONFIG.distDir}`;
13 | let destPath = `${CONFIG.publicDir}/dist`;
14 |
15 | console.log(`Copying compiled assets to ${destPath}`);
16 |
17 | await ensureDir(`${destPath}`);
18 | await copy(sourcePath, destPath);
19 | }//copyDist()
20 |
21 | async function copyDocs () {
22 | console.log('Copying static files for docs');
23 | // Directories to copy from docs/ to public/
24 | let dirs = [
25 | 'files',
26 | 'images',
27 | 'vendor',
28 | ];
29 |
30 | await ensureDir(`${CONFIG.publicDir}`);
31 |
32 | dirs.forEach(srcDir => {
33 | let sourcePath = `${CONFIG.docsDir}/${srcDir}`;
34 | let destPath = `${CONFIG.publicDir}/${srcDir}`;
35 | copy(sourcePath, destPath);
36 | });
37 | }//copyDocs();
38 |
39 | exports.copyDist = copyDist;
40 | exports.copyDocs = copyDocs;
41 |
--------------------------------------------------------------------------------
/scripts/_util/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /*
4 | * Wraps node apis in promises so that they can be used
5 | * in async/await logic.
6 | */
7 |
8 | const cp = require('child_process');
9 | const fs = require('fs');
10 | const { promisify } = require('util');
11 |
12 | exports.writeFile = promisify(fs.writeFile);
13 | exports.readFile = promisify(fs.readFile);
14 | exports.exec = promisify(cp.exec);
15 |
--------------------------------------------------------------------------------
/scripts/build.js:
--------------------------------------------------------------------------------
1 | // TODO: build out
2 |
--------------------------------------------------------------------------------
/scripts/clean.js:
--------------------------------------------------------------------------------
1 | // TODO: build out
2 |
--------------------------------------------------------------------------------
/scripts/cleanPublic.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict';
3 |
4 | // TODO: migrate to scripts/clean.js
5 |
6 | const { remove } = require('fs-extra');
7 |
8 | const CONFIG = require('./_config');
9 |
10 | (async function () {
11 | await remove(CONFIG.publicDir);
12 | })();
13 |
--------------------------------------------------------------------------------
/scripts/generate.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict';
3 |
4 | const { copyDocs, copyDist } = require('./_util/copy');
5 | const { generateAll } = require('./_generate');
6 |
7 | (async function () {
8 | await copyDist();
9 | await copyDocs();
10 | await generateAll();
11 | })();
12 |
--------------------------------------------------------------------------------
/scripts/lint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | echo "[LINT] Checking JavaScript"
4 | eslint -c .eslintrc.prod.json src
5 |
6 | echo "[LINT] Checking Stylesheets"
7 | stylelint "src/**/*.{scss,css}"
8 |
9 | #echo "Linting Markup"
10 | # TBD?
11 |
12 |
--------------------------------------------------------------------------------
/scripts/publish.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict';
3 |
4 | const { publishDocs } = require('./_publish/publishDocs');
5 |
6 | (async function () {
7 | await publishDocs();
8 | })();
9 |
--------------------------------------------------------------------------------
/scripts/revert-git-hooks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Revert actions performed in setup-git-hooks.sh
4 |
5 | if [ ! $CI ] # don't run in CI environment
6 | then
7 | echo "Reverting project git hooksPath..."
8 | git config --unset core.hooksPath
9 | echo "DONE"
10 | fi
11 |
--------------------------------------------------------------------------------
/scripts/serve.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict';
3 |
4 | const express = require('express');
5 | const { exec } = require('child_process');
6 |
7 | const CONFIG = require('./_config');
8 |
9 | // Create Express App
10 | const app = express();
11 | app.use('/helix-ui', express.static(CONFIG.publicDir));
12 | app.use('/', express.static(CONFIG.publicDir));
13 |
14 | // Start Server
15 | const server = app.listen(3000, () => {
16 | console.log('Serving http://127.0.0.1:3000');
17 | console.log('Use CTRL-C to stop the server.');
18 | });
19 |
20 | /**
21 | * 2019-11-01: Selenium isn't being used, right now, so I've
22 | * commented it out to speed up pipeline procesing. This will
23 | * need to be re-enabled when we get browser tests up and running.
24 | */
25 |
26 | // Start Selenium
27 | //const selenium = exec('yarn webdriver:start', { cwd: CONFIG.testDir });
28 | //if (selenium) {
29 | // console.log('selenium started');
30 | //}
31 |
32 |
33 | // Cleanup on Exit
34 | process.on('SIGINT', function () {
35 | console.log('Stopping...');
36 |
37 | // Cleanup Selenium
38 | //if (selenium) {
39 | // selenium.kill();
40 | //}
41 |
42 | // Close Server
43 | server.close(() => {
44 | process.exitCode = 1;
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/scripts/setup-git-hooks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # See revert-git-hooks.sh to revert actions in this script
4 |
5 | if [ ! $CI ] # don't run in CI environment
6 | then
7 | echo "Setting git-hooks/ as the project git hooksPath..."
8 | git config core.hooksPath git-hooks
9 | echo "DONE"
10 | fi
11 |
--------------------------------------------------------------------------------
/src/_bundle.es5.js:
--------------------------------------------------------------------------------
1 | import './polyfills/index.js';
2 | import * as HelixUI from './index.js';
3 |
4 | export default HelixUI;
5 |
--------------------------------------------------------------------------------
/src/_bundle.es6.js:
--------------------------------------------------------------------------------
1 | import * as HelixUI from './index.js';
2 |
3 | export default HelixUI;
4 |
--------------------------------------------------------------------------------
/src/elements/_base.scss:
--------------------------------------------------------------------------------
1 | @import "vars";
2 |
3 | *, *::before, *::after {
4 | box-sizing: border-box;
5 | // TODO: convert below properties into .inheritTypography() mixin
6 | color: inherit;
7 | font: inherit;
8 | letter-spacing: inherit;
9 | }
10 |
--------------------------------------------------------------------------------
/src/elements/hx-accordion-panel/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/elements/hx-accordion-panel/_shadow.scss:
--------------------------------------------------------------------------------
1 | @import "../base";
2 |
3 | #hxToggle {
4 | background-color: transparent;
5 | border: 1px;
6 | cursor: pointer;
7 | padding: 0 1rem 0 0;
8 | text-align: left;
9 | width: 100%;
10 |
11 | &[aria-expanded="true"] {
12 | .header__icon {
13 | transform: scaleY(-1);
14 | }
15 | }
16 |
17 | &[disabled] {
18 | cursor: not-allowed;
19 | }
20 | }
21 |
22 | .header {
23 | align-items: center;
24 | display: flex;
25 |
26 | &__content {
27 | flex-shrink: 0;
28 | flex-grow: 1;
29 | }
30 |
31 | &__icon {
32 | flex-shrink: 0;
33 | margin-left: 0.5rem;
34 | }
35 | }
36 |
37 | #hxBody {
38 | display: none;
39 |
40 | &[aria-expanded="true"] {
41 | display: block;
42 | }
43 | }
44 |
45 | button:focus {
46 | outline: none;
47 | box-shadow: 0 0 4px 0 $blue-700;
48 | box-shadow: 0 0 4px 0 var(--hxAccordianPanel-button-focus-box-shadow, $blue-700);
49 | }
50 |
--------------------------------------------------------------------------------
/src/elements/hx-alert/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/elements/hx-alert/_shadow.scss:
--------------------------------------------------------------------------------
1 | @import "../base";
2 |
3 | #hxAlert {
4 | display: flex;
5 | }
6 |
7 | button {
8 | align-self: flex-start;
9 | background-color: transparent;
10 | border: 0;
11 | cursor: pointer;
12 | }
13 |
14 | #hxIconWrapper {
15 | flex-shrink: 0;
16 | padding: 1rem;
17 | }
18 |
19 | #hxContent {
20 | flex-grow: 1;
21 | margin-right: 1rem;
22 | padding: 1rem 0;
23 | }
24 |
25 | #hxStatus {
26 | float: left;
27 | font-weight: 500;
28 | margin-right: 0.25rem;
29 | text-transform: uppercase;
30 |
31 | &:after {
32 | content: ":";
33 | }
34 |
35 | &:empty {
36 | display: none;
37 | }
38 | }
39 |
40 | #hxCta {
41 | flex-shrink: 0;
42 | font-weight: 500;
43 | padding: 1rem 0;
44 | text-transform: uppercase;
45 | white-space: nowrap;
46 |
47 | &:empty {
48 | display: none;
49 | }
50 | }
51 |
52 | #hxDismiss {
53 | flex-shrink: 0;
54 | height: 3rem;
55 | padding: 1rem;
56 | width: 3rem;
57 | }
58 |
59 | :host([persist]) {
60 | #hxDismiss {
61 | display: none;
62 | }
63 |
64 | #hxCta {
65 | margin-right: 1rem;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/elements/hx-beacon/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/elements/hx-beacon/_shadow.scss:
--------------------------------------------------------------------------------
1 | // inline external styles
2 | @import "components/button/config";
3 | @import "../base";
4 |
5 | // define Shadow DOM styles
6 | :host {
7 | #hxDismiss {
8 | @include hxButton--reset;
9 |
10 | #hxBeaconPulse {
11 | -webkit-animation: hx-pulse 2s infinite linear;
12 | animation: hx-pulse 2s infinite linear;
13 | border-radius: 3rem;
14 | box-shadow: 0 0 1px 1px var(--hxBeacon, $gray-750);
15 | content: "";
16 | height: 1rem;
17 | left: 0;
18 | margin: 0;
19 | padding: 0;
20 | position: absolute;
21 | top: 0;
22 | -webkit-transform-origin: 50% 50%;
23 | transform-origin: 50% 50%;
24 | width: 1rem;
25 | cursor: pointer;
26 | }
27 | }
28 |
29 | @keyframes hx-pulse {
30 | 0% {
31 | transform: scale(1);
32 | opacity: 1;
33 | }
34 |
35 | 100% {
36 | transform: scale(2.5);
37 | opacity: 0;
38 | }
39 | }
40 |
41 | // Safari
42 | @-webkit-keyframes hx-pulse {
43 | 0% {
44 | transform: scale(1);
45 | opacity: 1;
46 | }
47 |
48 | 100% {
49 | transform: scale(2.5);
50 | opacity: 0;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/elements/hx-busy/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 |
3 | /**
4 | * Defines behavior for the `` element.
5 | *
6 | * @extends HXElement
7 | * @hideconstructor
8 | * @since 0.4.0
9 | */
10 | export class HXBusyElement extends HXElement {
11 | static get is () {
12 | return 'hx-busy';
13 | }
14 |
15 | $onConnect () {
16 | this.$upgradeProperty('paused');
17 | this.$defaultAttribute('aria-hidden', true);
18 | }
19 |
20 | /**
21 | * Pause or resume animation.
22 | *
23 | * @default false
24 | * @type {Boolean}
25 | */
26 | get paused () {
27 | return this.hasAttribute('paused');
28 | }
29 | set paused (isPaused) {
30 | if (isPaused) {
31 | this.setAttribute('paused', '');
32 | } else {
33 | this.removeAttribute('paused');
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/elements/hx-checkbox-control/index.js:
--------------------------------------------------------------------------------
1 | import { HXFormControlElement } from '../../interfaces/HXFormControlElement/index.js';
2 |
3 | /**
4 | * Defines behavior for the `` element.
5 | *
6 | * @extends HXFormControlElement
7 | * @hideconstructor
8 | * @since 0.16.0
9 | */
10 | export class HXCheckboxControlElement extends HXFormControlElement {
11 | /** @override */
12 | static get is () {
13 | return 'hx-checkbox-control';
14 | }
15 |
16 | /**
17 | * Fetch the first ` ` descendant
18 | *
19 | * @override
20 | * @readonly
21 | * @type {?HTMLInputElement}
22 | */
23 | get controlElement () {
24 | return this.querySelector('input[type="checkbox"]');
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/elements/hx-checkbox/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/elements/hx-checkbox/_shadow.scss:
--------------------------------------------------------------------------------
1 | @import "../base";
2 |
3 | #hxCheckbox {
4 | align-items: center;
5 | display: grid;
6 | font-size: 10px;
7 | grid-template-areas: "icon";
8 | height: 100%;
9 | justify-content: center;
10 | width: 100%;
11 | }
12 |
13 | // icons
14 | #hxMinus,
15 | #hxTick {
16 | grid-area: icon;
17 | height: 1em;
18 | line-height: 1;
19 | width: 1em;
20 | }
21 |
22 | #hxMinus {
23 | display: var(--hxMinus-display, none);
24 | }
25 |
26 | #hxTick {
27 | display: var(--hxTick-display, none);
28 | }
29 |
--------------------------------------------------------------------------------
/src/elements/hx-checkbox/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 |
3 | import shadowMarkup from './_shadow.html';
4 | import shadowStyles from './_shadow.scss';
5 |
6 | /**
7 | * Applies Shadow DOM to the `` facade element.
8 | *
9 | * @extends HXElement
10 | * @hideconstructor
11 | */
12 | export class HXCheckboxElement extends HXElement {
13 | /** @override */
14 | static get is () {
15 | return 'hx-checkbox';
16 | }
17 |
18 | /** @override */
19 | static get template () {
20 | return `${shadowMarkup}`;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/elements/hx-div/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/elements/hx-div/_shadow.scss:
--------------------------------------------------------------------------------
1 | @import "../base";
2 |
3 | // @supports used to prevent IE from loading the ShadyCSS-rewritten styles.
4 | // This is so we can write shorter, less-specific CSS selectors in order
5 | // to apply ShadyCSS overrides in the LightDOM.
6 | @supports (--skip-ie: true) {
7 | :host {
8 | --hxPadding--base: 0;
9 | --hxPaddingTop: var(--hxPadding--base);
10 | --hxPaddingRight: var(--hxPadding--base);
11 | --hxPaddingBottom: var(--hxPadding--base);
12 | --hxPaddingLeft: var(--hxPadding--base);
13 | --hxPadding:
14 | var(--hxPaddingTop)
15 | var(--hxPaddingRight)
16 | var(--hxPaddingBottom)
17 | var(--hxPaddingLeft);
18 |
19 | #hxDiv {
20 | padding: var(--hxPadding, 0);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/elements/hx-drawer/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/elements/hx-drop-fence/_shadow.html:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/elements/hx-drop-fence/_shadow.scss:
--------------------------------------------------------------------------------
1 | @import "../base";
2 |
3 | #hxDropFence {
4 | align-items: center;
5 | display: flex;
6 | flex-direction: column;
7 | height: 100%;
8 | justify-content: center;
9 | width: 100%;
10 |
11 | > div {
12 | margin-top: 0.5rem;
13 | max-width: 30rem; // 480px
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/elements/hx-drop-fence/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 |
3 | import shadowMarkup from './_shadow.html';
4 | import shadowStyles from './_shadow.scss';
5 |
6 | /**
7 | * Defines behavior for the `` element.
8 | *
9 | * @extends HXElement
10 | * @hideconstructor
11 | * @since 0.14.0
12 | */
13 | export class HXDropFenceElement extends HXElement {
14 | static get is () {
15 | return 'hx-drop-fence';
16 | }
17 |
18 | static get template () {
19 | return `${shadowMarkup}`;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/elements/hx-email-control/index.js:
--------------------------------------------------------------------------------
1 | import { HXFormControlElement } from '../../interfaces/HXFormControlElement/index.js';
2 |
3 | /**
4 | * Defines behavior for the `` element.
5 | * @extends HXFormControlElement
6 | * @hideconstructor
7 | * @since 0.20.0
8 | */
9 |
10 | export class HXEmailControl extends HXFormControlElement {
11 | /** @override */
12 | static get is () {
13 | return 'hx-email-control';
14 | }
15 |
16 | /**
17 | * Fetch the first ` ` with 'type="email"' descendant,
18 | * whether implicit (` `) or explicit
19 | * (` `).
20 | *
21 | * @override
22 | * @readonly
23 | * @type {?HTMLInputElement}
24 | */
25 | get controlElement () {
26 | return this.querySelector('input:not([type]), input[type="email"]');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/elements/hx-error/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/elements/hx-error/_shadow.scss:
--------------------------------------------------------------------------------
1 | @import "../base";
2 |
3 | #hxError {
4 | display: inline-flex;
5 |
6 | * + * {
7 | margin-left: 0.25rem;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/elements/hx-error/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 |
3 | import shadowMarkup from './_shadow.html';
4 | import shadowStyles from './_shadow.scss';
5 |
6 | /**
7 | * Defines behavior for the `` element.
8 | *
9 | * @extends HXElement
10 | * @hideconstructor
11 | * @since 0.4.0
12 | */
13 | export class HXErrorElement extends HXElement {
14 | static get is () {
15 | return 'hx-error';
16 | }
17 |
18 | static get template () {
19 | return `${shadowMarkup}`;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/elements/hx-file-control/index.js:
--------------------------------------------------------------------------------
1 | import { HXFormControlElement } from '../../interfaces/HXFormControlElement/index.js';
2 |
3 | /**
4 | * Defines behavior for the `` element.
5 | *
6 | * @extends HXFormControlElement
7 | * @hideconstructor
8 | */
9 | export class HXFileControlElement extends HXFormControlElement {
10 | /** @override */
11 | static get is () {
12 | return 'hx-file-control';
13 | }
14 |
15 | /**
16 | * Fetch the first ` ` descendant
17 | *
18 | * @override
19 | * @readonly
20 | * @type {?HTMLInputElement}
21 | */
22 | get controlElement () {
23 | return this.querySelector('input[type="file"]');
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/elements/hx-file-icon/_shadow.html:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/elements/hx-file-icon/_shadow.scss:
--------------------------------------------------------------------------------
1 | @import "../base";
2 |
3 | #hxFileIcon {
4 | position: relative;
5 |
6 | #hxBase {
7 | font-size: 2.5rem;
8 | height: 1em;
9 | }
10 |
11 | #hxOverlay {
12 | align-items: center;
13 | display: flex;
14 | flex-direction: column;
15 | height: 100%;
16 | justify-content: center;
17 | line-height: 1;
18 | position: absolute;
19 | text-align: center;
20 | top: 0;
21 | width: 100%;
22 | }
23 |
24 | #hxIcon {
25 | font-size: 1rem;
26 | height: 1em;
27 | }
28 |
29 | #hxExt {
30 | display: none;
31 | font-size: 0.5rem;
32 | line-height: 1.5;
33 | margin-top: 1px;
34 | text-transform: uppercase;
35 | }
36 | }
37 |
38 | :host([extension]) {
39 | #hxFileIcon {
40 | #hxOverlay {
41 | height: auto;
42 | top: 0.5rem;
43 | }
44 |
45 | #hxExt {
46 | display: block;
47 | }
48 | }
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/src/elements/hx-file-input/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/elements/hx-file-input/_shadow.scss:
--------------------------------------------------------------------------------
1 | @import "../base";
2 |
3 | #hxIcon {
4 | display: none;
5 | }
6 |
7 | #hxLabel {
8 | margin-left: 0.25rem;
9 | }
10 |
11 | :host([icon]) {
12 | #hxIcon {
13 | display: inline-block;
14 | }
15 | }
16 |
17 | :host([title]) {
18 | #hxLabel {
19 | display: none;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/elements/hx-file-tile/_shadow.html:
--------------------------------------------------------------------------------
1 |
34 |
--------------------------------------------------------------------------------
/src/elements/hx-icon/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/elements/hx-icon/_shadow.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | background-color: transparent;
3 | color: currentColor;
4 | display: inline-block;
5 | flex-shrink: 0;
6 | height: 1em;
7 | width: 1em;
8 |
9 | #hxIcon {
10 | box-sizing: border-box;
11 | display: block;
12 | flex-shrink: 0;
13 | height: 100%;
14 | line-height: 1;
15 | width: 100%;
16 |
17 | svg {
18 | fill: currentColor;
19 | height: auto; // because IE
20 | stroke: none;
21 | vertical-align: bottom;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/elements/hx-menu/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 | import { Positionable } from '../traits/Positionable.js';
3 | import { mix } from '../../utils';
4 |
5 | class _ProtoClass extends mix(HXElement, Positionable) {}
6 |
7 | /**
8 | * Defines behavior for the `` element.
9 | *
10 | * @extends HXElement
11 | * @extends Positionable
12 | * @hideconstructor
13 | * @since 0.2.0
14 | */
15 | export class HXMenuElement extends _ProtoClass {
16 | static get is () {
17 | return 'hx-menu';
18 | }
19 |
20 | /** @override */
21 | $onCreate () {
22 | super.$onCreate();
23 | this.DEFAULT_POSITION = 'bottom-start';
24 | }
25 |
26 | /** @override */
27 | $onConnect () {
28 | super.$onConnect();
29 | this.$defaultAttribute('role', 'menu');
30 | this.setAttribute('aria-expanded', this.open);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/elements/hx-menuitem/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 |
3 | /**
4 | * Defines behavior for the `` element.
5 | *
6 | * @extends HXElement
7 | * @hideconstructor
8 | * @since 0.2.0
9 | */
10 | export class HXMenuitemElement extends HXElement {
11 | static get is () {
12 | return 'hx-menuitem';
13 | }
14 |
15 | $onConnect () {
16 | this.$defaultAttribute('role', 'menuitem');
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/elements/hx-modal/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/elements/hx-password-control/index.js:
--------------------------------------------------------------------------------
1 | import { HXFormControlElement } from '../../interfaces/HXFormControlElement/index.js';
2 |
3 | /**
4 | * Defines behavior for the `` element.
5 | *
6 | * @extends HXFormControlElement
7 | * @hideconstructor
8 | * @since 0.20.0
9 | */
10 | export class HXPasswordElement extends HXFormControlElement {
11 | /** @override */
12 | static get is () {
13 | return 'hx-password-control';
14 | }
15 |
16 | /**
17 | * Fetch the first ` ` descendant,
18 | * whether implicit (` `) or explicit
19 | * (` `).
20 | *
21 | * @override
22 | * @readonly
23 | * @type {?HTMLInputElement}
24 | */
25 | get controlElement () {
26 | return this.querySelector('input:not([type]), input[type="password"]');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/elements/hx-pill/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/elements/hx-pill/_shadow.scss:
--------------------------------------------------------------------------------
1 | // import configs
2 | @import "components/button/config";
3 |
4 | // inline external styles
5 | @import "../base";
6 |
7 | // define Shadow DOM styles
8 | :host {
9 | #hxPill {
10 | display: flex;
11 | height: 100%;
12 | padding: 0 1rem;
13 | white-space: nowrap;
14 | width: 100%;
15 | }
16 |
17 | #hxDismiss {
18 | @include hxButton--reset;
19 |
20 | align-items: center;
21 | color: var(--hxDismiss-color, $gray-600);
22 | display: inline-flex;
23 | justify-content: center;
24 | margin: 0 -0.5rem 0 0;
25 | width: 1.5em;
26 |
27 | > span {
28 | font-size: 0.75em;
29 | }
30 |
31 | &:hover {
32 | color: var(--hxDismiss-color--hover, $gray-1000);
33 | }
34 | }
35 | }
36 |
37 | :host([persist]) {
38 | #hxDismiss {
39 | display: none;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/elements/hx-popover/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/elements/hx-popover/_shadow.scss:
--------------------------------------------------------------------------------
1 | @import "vars";
2 | @import "../base";
3 | @import "../has-arrow";
4 |
5 | #hxPopover {
6 | background-color: var(--hxBackgroundColor, $gray-0);
7 | border-color: var(--hxBorderColor, $gray-300);
8 | border-style: solid;
9 | border-width: 1px;
10 | box-shadow: $layering-shadow;
11 | }
12 |
--------------------------------------------------------------------------------
/src/elements/hx-progress/_shadow.html:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/elements/hx-progress/_shadow.scss:
--------------------------------------------------------------------------------
1 | #hxProgress {
2 | height: 100%;
3 |
4 | #hxFill {
5 | background-color: currentColor;
6 | box-sizing: border-box;
7 | height: 100%;
8 | width: 0%;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/elements/hx-radio-control/index.js:
--------------------------------------------------------------------------------
1 | import { HXFormControlElement } from '../../interfaces/HXFormControlElement/index.js';
2 |
3 | /**
4 | * Defines behavior for the `` element.
5 | *
6 | * @extends HXFormControlElement
7 | * @hideconstructor
8 | * @since 0.16.0
9 | */
10 | export class HXRadioControlElement extends HXFormControlElement {
11 | /** @override */
12 | static get is () {
13 | return 'hx-radio-control';
14 | }
15 |
16 | /**
17 | * Fetch the first ` ` descendant
18 | *
19 | * @override
20 | * @readonly
21 | * @type {?HTMLInputElement}
22 | */
23 | get controlElement () {
24 | return this.querySelector('input[type="radio"]');
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/elements/hx-radio/_shadow.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
--------------------------------------------------------------------------------
/src/elements/hx-radio/_shadow.scss:
--------------------------------------------------------------------------------
1 | // TBD
2 |
--------------------------------------------------------------------------------
/src/elements/hx-radio/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 |
3 | import shadowMarkup from './_shadow.html';
4 | import shadowStyles from './_shadow.scss';
5 |
6 | /**
7 | * Applies Shadow DOM to the `` facade element.
8 | *
9 | * @extends HXElement
10 | * @hideconstructor
11 | */
12 | export class HXRadioElement extends HXElement {
13 | /** @override */
14 | static get is () {
15 | return 'hx-radio';
16 | }
17 |
18 | /** @override */
19 | static get template () {
20 | return `${shadowMarkup}`;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/elements/hx-search-assistance/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 | import { Positionable } from '../traits/Positionable.js';
3 | import { mix } from '../../utils';
4 |
5 | class _ProtoClass extends mix(HXElement, Positionable) {}
6 |
7 | /**
8 | * Defines behavior for the `` element.
9 | *
10 | * @extends HXElement
11 | * @extends Positionable
12 | * @hideconstructor
13 | * @see HXSearchElement
14 | * @since 0.6.0
15 | */
16 | export class HXSearchAssistanceElement extends _ProtoClass {
17 | static get is () {
18 | return 'hx-search-assistance';
19 | }
20 |
21 | /** @override */
22 | $onCreate () {
23 | super.$onCreate();
24 | this.DEFAULT_POSITION = 'bottom-start';
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/elements/hx-search/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/elements/hx-search/_shadow.scss:
--------------------------------------------------------------------------------
1 | // import configs
2 | @import "mixins";
3 | @import "components/form/config";
4 |
5 | // inline external styles
6 | @import "../base";
7 |
8 | // TODO: add CSS custom props for theming hooks
9 |
10 | // define Shadow DOM styles
11 | input::-ms-clear {
12 | display: none;
13 | }
14 |
15 | :host {
16 | #hxSearch {
17 | -ms-grid-column-align: start;
18 | -ms-grid-columns: 2rem 1fr;
19 | -ms-grid-rows: 1fr;
20 | align-items: center;
21 | display: -ms-grid; // Legacy (IE)
22 | display: grid; // Modern
23 | grid-template-columns: 2rem 1fr;
24 | height: 100%;
25 | }
26 |
27 | #hxIcon {
28 | color: $gray-700;
29 | line-height: 1;
30 | margin: auto 0.5em;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/elements/hx-search/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 |
3 | import shadowMarkup from './_shadow.html';
4 | import shadowStyles from './_shadow.scss';
5 |
6 | /**
7 | * Defines behavior for the `` element.
8 | *
9 | * @extends HXElement
10 | * @hideconstructor
11 | * @see HXSearchAssistanceElement
12 | * @since 0.4.0
13 | */
14 | export class HXSearchElement extends HXElement {
15 | static get is () {
16 | return 'hx-search';
17 | }
18 |
19 | static get template () {
20 | return `${shadowMarkup}`;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/elements/hx-select-control/index.js:
--------------------------------------------------------------------------------
1 | import { HXFormControlElement } from '../../interfaces/HXFormControlElement/index.js';
2 |
3 | /**
4 | * Defines behavior for the `` element.
5 | *
6 | * @extends HXFormControlElement
7 | * @hideconstructor
8 | * @since 0.16.0
9 | */
10 | export class HXSelectControlElement extends HXFormControlElement {
11 | /** @override */
12 | static get is () {
13 | return 'hx-select-control';
14 | }
15 |
16 | /**
17 | * Fetch the first `` descendant
18 | *
19 | * @override
20 | * @readonly
21 | * @type {?HTMLSelectElement}
22 | */
23 | get controlElement () {
24 | return this.querySelector('select');
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/elements/hx-select/_shadow.html:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/elements/hx-select/_shadow.scss:
--------------------------------------------------------------------------------
1 | @import "vars";
2 |
3 | // Hide ShadowDOM content for IE
4 | #hxSelect {
5 | display: none;
6 | }
7 |
8 | // Show ShadowDOM content for evergreen browsers
9 | //
10 | // auto 2.5rem
11 | // +---------------------------+---------+
12 | // | . ("window") | trigger | auto
13 | // +---------------------------+---------+
14 | @supports (display: grid) {
15 | #hxSelect {
16 | box-sizing: border-box;
17 | display: grid;
18 | grid-template-areas: ". trigger";
19 | grid-template-columns: auto 2.5rem;
20 | height: 100%;
21 | width: 100%;
22 | }
23 |
24 | #hxTrigger {
25 | align-items: center;
26 | background-color: var(--hxTrigger-backgroundColor, $gray-0);
27 | box-sizing: border-box;
28 | color: inherit;
29 | display: flex;
30 | grid-area: trigger;
31 | height: 100%;
32 | justify-content: center;
33 | opacity: 1;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/elements/hx-select/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 |
3 | import shadowMarkup from './_shadow.html';
4 | import shadowStyles from './_shadow.scss';
5 |
6 | /**
7 | * Applies Shadow DOM to the `` facade element.
8 | *
9 | * @extends HXElement
10 | * @hideconstructor
11 | * @since 0.16.0
12 | */
13 | export class HXSelectElement extends HXElement {
14 | /** @override */
15 | static get is () {
16 | return 'hx-select';
17 | }
18 |
19 | /** @override */
20 | static get template () {
21 | return `${shadowMarkup}`;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/elements/hx-switch/_shadow.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/elements/hx-switch/_shadow.scss:
--------------------------------------------------------------------------------
1 | // TBD
2 |
--------------------------------------------------------------------------------
/src/elements/hx-tabcontent/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 | import { onScroll } from '../../utils';
3 |
4 | /**
5 | * Defines behavior for the `` element.
6 | *
7 | * @extends HXElement
8 | * @hideconstructor
9 | * @since 0.2.0
10 | */
11 | export class HXTabcontentElement extends HXElement {
12 | static get is () {
13 | return 'hx-tabcontent';
14 | }
15 |
16 | $onConnect () {
17 | this.$defaultAttribute('role', 'presentation');
18 | this.addEventListener('scroll', onScroll);
19 | }
20 |
21 | $onDisconnect () {
22 | this.removeEventListener('scroll', onScroll);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/elements/hx-tablist/index.js:
--------------------------------------------------------------------------------
1 | import { HXElement } from '../../interfaces/HXElement/index.js';
2 |
3 | /**
4 | * Defines behavior for the `` element.
5 | *
6 | * @extends HXElement
7 | * @hideconstructor
8 | * @since 0.2.0
9 | */
10 | export class HXTablistElement extends HXElement {
11 | static get is () {
12 | return 'hx-tablist';
13 | }
14 |
15 | $onConnect () {
16 | this.$defaultAttribute('role', 'tablist');
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/elements/hx-text-control/index.js:
--------------------------------------------------------------------------------
1 | import { HXFormControlElement } from '../../interfaces/HXFormControlElement/index.js';
2 |
3 | /**
4 | * Defines behavior for the `` element.
5 | *
6 | * @extends HXFormControlElement
7 | * @hideconstructor
8 | * @since 0.16.0
9 | */
10 | export class HXTextControlElement extends HXFormControlElement {
11 | /** @override */
12 | static get is () {
13 | return 'hx-text-control';
14 | }
15 |
16 | /**
17 | * Fetch the first text ` ` descendant,
18 | * whether implicit (` `) or explicit
19 | * (` `).
20 | *
21 | * @override
22 | * @readonly
23 | * @type {?HTMLInputElement}
24 | */
25 | get controlElement () {
26 | return this.querySelector('input:not([type]), input[type="text"]');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/elements/hx-textarea-control/index.js:
--------------------------------------------------------------------------------
1 | import { HXFormControlElement } from '../../interfaces/HXFormControlElement/index.js';
2 |
3 | /**
4 | * Defines behavior for the `` element.
5 | *
6 | * @extends HXFormControlElement
7 | * @hideconstructor
8 | * @since 0.16.0
9 | */
10 | export class HXTextareaControlElement extends HXFormControlElement {
11 | /** @override */
12 | static get is () {
13 | return 'hx-textarea-control';
14 | }
15 |
16 | /**
17 | * Fetch the first text `