@lo-tek/interfaces 0.0.0 → 0.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3254 -0
- package/LICENSE +21 -0
- package/README.md +128 -1
- package/agent/astro.md +400 -0
- package/agent/bundles.md +429 -0
- package/agent/datastar.md +409 -0
- package/agent/html.md +388 -0
- package/agent/react.md +440 -0
- package/agent/templates.md +472 -0
- package/core/lotek-core.wasm +0 -0
- package/core/lotek.wasm +0 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +14 -0
- package/dist/cli.js.map +1 -0
- package/dist/components/css/accordion/accordion.d.ts +37 -0
- package/dist/components/css/accordion/accordion.d.ts.map +1 -0
- package/dist/components/css/accordion/accordion.js +31 -0
- package/dist/components/css/accordion/accordion.js.map +1 -0
- package/dist/components/css/alert/alert.d.ts +35 -0
- package/dist/components/css/alert/alert.d.ts.map +1 -0
- package/dist/components/css/alert/alert.js +29 -0
- package/dist/components/css/alert/alert.js.map +1 -0
- package/dist/components/css/avatar/avatar.d.ts +40 -0
- package/dist/components/css/avatar/avatar.d.ts.map +1 -0
- package/dist/components/css/avatar/avatar.js +30 -0
- package/dist/components/css/avatar/avatar.js.map +1 -0
- package/dist/components/css/badge/badge.d.ts +24 -0
- package/dist/components/css/badge/badge.d.ts.map +1 -0
- package/dist/components/css/badge/badge.js +24 -0
- package/dist/components/css/badge/badge.js.map +1 -0
- package/dist/components/css/breadcrumbs/breadcrumbs.d.ts +26 -0
- package/dist/components/css/breadcrumbs/breadcrumbs.d.ts.map +1 -0
- package/dist/components/css/breadcrumbs/breadcrumbs.js +24 -0
- package/dist/components/css/breadcrumbs/breadcrumbs.js.map +1 -0
- package/dist/components/css/button/button.d.ts +26 -0
- package/dist/components/css/button/button.d.ts.map +1 -0
- package/dist/components/css/button/button.js +25 -0
- package/dist/components/css/button/button.js.map +1 -0
- package/dist/components/css/card/card.d.ts +36 -0
- package/dist/components/css/card/card.d.ts.map +1 -0
- package/dist/components/css/card/card.js +28 -0
- package/dist/components/css/card/card.js.map +1 -0
- package/dist/components/css/checkbox/checkbox.d.ts +32 -0
- package/dist/components/css/checkbox/checkbox.d.ts.map +1 -0
- package/dist/components/css/checkbox/checkbox.js +27 -0
- package/dist/components/css/checkbox/checkbox.js.map +1 -0
- package/dist/components/css/divider/divider.d.ts +29 -0
- package/dist/components/css/divider/divider.d.ts.map +1 -0
- package/dist/components/css/divider/divider.js +23 -0
- package/dist/components/css/divider/divider.js.map +1 -0
- package/dist/components/css/error-text/error-text.d.ts +24 -0
- package/dist/components/css/error-text/error-text.d.ts.map +1 -0
- package/dist/components/css/error-text/error-text.js +18 -0
- package/dist/components/css/error-text/error-text.js.map +1 -0
- package/dist/components/css/fieldset/fieldset.d.ts +55 -0
- package/dist/components/css/fieldset/fieldset.d.ts.map +1 -0
- package/dist/components/css/fieldset/fieldset.js +39 -0
- package/dist/components/css/fieldset/fieldset.js.map +1 -0
- package/dist/components/css/file-upload/file-upload.d.ts +41 -0
- package/dist/components/css/file-upload/file-upload.d.ts.map +1 -0
- package/dist/components/css/file-upload/file-upload.js +32 -0
- package/dist/components/css/file-upload/file-upload.js.map +1 -0
- package/dist/components/css/heading/heading.d.ts +29 -0
- package/dist/components/css/heading/heading.d.ts.map +1 -0
- package/dist/components/css/heading/heading.js +23 -0
- package/dist/components/css/heading/heading.js.map +1 -0
- package/dist/components/css/help-text/help-text.d.ts +24 -0
- package/dist/components/css/help-text/help-text.d.ts.map +1 -0
- package/dist/components/css/help-text/help-text.js +23 -0
- package/dist/components/css/help-text/help-text.js.map +1 -0
- package/dist/components/css/icon/icon.d.ts +34 -0
- package/dist/components/css/icon/icon.d.ts.map +1 -0
- package/dist/components/css/icon/icon.js +25 -0
- package/dist/components/css/icon/icon.js.map +1 -0
- package/dist/components/css/input/input.d.ts +40 -0
- package/dist/components/css/input/input.d.ts.map +1 -0
- package/dist/components/css/input/input.js +45 -0
- package/dist/components/css/input/input.js.map +1 -0
- package/dist/components/css/label/label.d.ts +33 -0
- package/dist/components/css/label/label.d.ts.map +1 -0
- package/dist/components/css/label/label.js +23 -0
- package/dist/components/css/label/label.js.map +1 -0
- package/dist/components/css/link/link.d.ts +28 -0
- package/dist/components/css/link/link.d.ts.map +1 -0
- package/dist/components/css/link/link.js +20 -0
- package/dist/components/css/link/link.js.map +1 -0
- package/dist/components/css/list/list.d.ts +31 -0
- package/dist/components/css/list/list.d.ts.map +1 -0
- package/dist/components/css/list/list.js +25 -0
- package/dist/components/css/list/list.js.map +1 -0
- package/dist/components/css/pagination/pagination.d.ts +27 -0
- package/dist/components/css/pagination/pagination.d.ts.map +1 -0
- package/dist/components/css/pagination/pagination.js +25 -0
- package/dist/components/css/pagination/pagination.js.map +1 -0
- package/dist/components/css/paragraph/paragraph.d.ts +36 -0
- package/dist/components/css/paragraph/paragraph.d.ts.map +1 -0
- package/dist/components/css/paragraph/paragraph.js +26 -0
- package/dist/components/css/paragraph/paragraph.js.map +1 -0
- package/dist/components/css/progress/progress.d.ts +53 -0
- package/dist/components/css/progress/progress.d.ts.map +1 -0
- package/dist/components/css/progress/progress.js +38 -0
- package/dist/components/css/progress/progress.js.map +1 -0
- package/dist/components/css/radio/radio.d.ts +32 -0
- package/dist/components/css/radio/radio.d.ts.map +1 -0
- package/dist/components/css/radio/radio.js +27 -0
- package/dist/components/css/radio/radio.js.map +1 -0
- package/dist/components/css/search/search.d.ts +34 -0
- package/dist/components/css/search/search.d.ts.map +1 -0
- package/dist/components/css/search/search.js +32 -0
- package/dist/components/css/search/search.js.map +1 -0
- package/dist/components/css/select/select.d.ts +40 -0
- package/dist/components/css/select/select.d.ts.map +1 -0
- package/dist/components/css/select/select.js +31 -0
- package/dist/components/css/select/select.js.map +1 -0
- package/dist/components/css/shared.d.ts +90 -0
- package/dist/components/css/shared.d.ts.map +1 -0
- package/dist/components/css/shared.js +167 -0
- package/dist/components/css/shared.js.map +1 -0
- package/dist/components/css/skeleton/skeleton.d.ts +29 -0
- package/dist/components/css/skeleton/skeleton.d.ts.map +1 -0
- package/dist/components/css/skeleton/skeleton.js +23 -0
- package/dist/components/css/skeleton/skeleton.js.map +1 -0
- package/dist/components/css/skip-link/skip-link.d.ts +18 -0
- package/dist/components/css/skip-link/skip-link.d.ts.map +1 -0
- package/dist/components/css/skip-link/skip-link.js +16 -0
- package/dist/components/css/skip-link/skip-link.js.map +1 -0
- package/dist/components/css/spinner/spinner.d.ts +33 -0
- package/dist/components/css/spinner/spinner.d.ts.map +1 -0
- package/dist/components/css/spinner/spinner.js +25 -0
- package/dist/components/css/spinner/spinner.js.map +1 -0
- package/dist/components/css/sr-only/sr-only.d.ts +17 -0
- package/dist/components/css/sr-only/sr-only.d.ts.map +1 -0
- package/dist/components/css/sr-only/sr-only.js +15 -0
- package/dist/components/css/sr-only/sr-only.js.map +1 -0
- package/dist/components/css/switch/switch.d.ts +37 -0
- package/dist/components/css/switch/switch.d.ts.map +1 -0
- package/dist/components/css/switch/switch.js +29 -0
- package/dist/components/css/switch/switch.js.map +1 -0
- package/dist/components/css/table/table.d.ts +76 -0
- package/dist/components/css/table/table.d.ts.map +1 -0
- package/dist/components/css/table/table.js +59 -0
- package/dist/components/css/table/table.js.map +1 -0
- package/dist/components/css/tag/tag.d.ts +35 -0
- package/dist/components/css/tag/tag.d.ts.map +1 -0
- package/dist/components/css/tag/tag.js +27 -0
- package/dist/components/css/tag/tag.js.map +1 -0
- package/dist/components/css/textarea/textarea.d.ts +23 -0
- package/dist/components/css/textarea/textarea.d.ts.map +1 -0
- package/dist/components/css/textarea/textarea.js +18 -0
- package/dist/components/css/textarea/textarea.js.map +1 -0
- package/dist/components/css/toggle-group/toggle-group.d.ts +31 -0
- package/dist/components/css/toggle-group/toggle-group.d.ts.map +1 -0
- package/dist/components/css/toggle-group/toggle-group.js +29 -0
- package/dist/components/css/toggle-group/toggle-group.js.map +1 -0
- package/dist/components/css/tooltip/tooltip.d.ts +31 -0
- package/dist/components/css/tooltip/tooltip.d.ts.map +1 -0
- package/dist/components/css/tooltip/tooltip.js +29 -0
- package/dist/components/css/tooltip/tooltip.js.map +1 -0
- package/dist/components/default-texts.d.ts +35 -0
- package/dist/components/default-texts.d.ts.map +1 -0
- package/dist/components/default-texts.js +35 -0
- package/dist/components/default-texts.js.map +1 -0
- package/dist/components/events.d.ts +77 -0
- package/dist/components/events.d.ts.map +1 -0
- package/dist/components/events.js +3 -0
- package/dist/components/events.js.map +1 -0
- package/dist/components/frame/dialog/dialog.d.ts +122 -0
- package/dist/components/frame/dialog/dialog.d.ts.map +1 -0
- package/dist/components/frame/dialog/dialog.js +112 -0
- package/dist/components/frame/dialog/dialog.js.map +1 -0
- package/dist/components/frame/dialog/lt-dialog.d.ts +104 -0
- package/dist/components/frame/dialog/lt-dialog.d.ts.map +1 -0
- package/dist/components/frame/dialog/lt-dialog.js +431 -0
- package/dist/components/frame/dialog/lt-dialog.js.map +1 -0
- package/dist/components/frame/error-summary/error-summary.d.ts +40 -0
- package/dist/components/frame/error-summary/error-summary.d.ts.map +1 -0
- package/dist/components/frame/error-summary/error-summary.js +32 -0
- package/dist/components/frame/error-summary/error-summary.js.map +1 -0
- package/dist/components/frame/error-summary/lt-error-summary.d.ts +82 -0
- package/dist/components/frame/error-summary/lt-error-summary.d.ts.map +1 -0
- package/dist/components/frame/error-summary/lt-error-summary.js +302 -0
- package/dist/components/frame/error-summary/lt-error-summary.js.map +1 -0
- package/dist/components/frame/field/field-core.d.ts +92 -0
- package/dist/components/frame/field/field-core.d.ts.map +1 -0
- package/dist/components/frame/field/field-core.js +63 -0
- package/dist/components/frame/field/field-core.js.map +1 -0
- package/dist/components/frame/field/lt-field.d.ts +173 -0
- package/dist/components/frame/field/lt-field.d.ts.map +1 -0
- package/dist/components/frame/field/lt-field.js +580 -0
- package/dist/components/frame/field/lt-field.js.map +1 -0
- package/dist/components/frame/popover/lt-popover.d.ts +132 -0
- package/dist/components/frame/popover/lt-popover.d.ts.map +1 -0
- package/dist/components/frame/popover/lt-popover.js +490 -0
- package/dist/components/frame/popover/lt-popover.js.map +1 -0
- package/dist/components/frame/popover/popover.d.ts +49 -0
- package/dist/components/frame/popover/popover.d.ts.map +1 -0
- package/dist/components/frame/popover/popover.js +64 -0
- package/dist/components/frame/popover/popover.js.map +1 -0
- package/dist/components/frame/session-timeout/lt-session-timeout.d.ts +198 -0
- package/dist/components/frame/session-timeout/lt-session-timeout.d.ts.map +1 -0
- package/dist/components/frame/session-timeout/lt-session-timeout.js +573 -0
- package/dist/components/frame/session-timeout/lt-session-timeout.js.map +1 -0
- package/dist/components/frame/session-timeout/session-timeout.d.ts +113 -0
- package/dist/components/frame/session-timeout/session-timeout.d.ts.map +1 -0
- package/dist/components/frame/session-timeout/session-timeout.js +101 -0
- package/dist/components/frame/session-timeout/session-timeout.js.map +1 -0
- package/dist/components/frame/suggestion/lt-suggestion.d.ts +361 -0
- package/dist/components/frame/suggestion/lt-suggestion.d.ts.map +1 -0
- package/dist/components/frame/suggestion/lt-suggestion.js +1152 -0
- package/dist/components/frame/suggestion/lt-suggestion.js.map +1 -0
- package/dist/components/frame/suggestion/suggestion.d.ts +143 -0
- package/dist/components/frame/suggestion/suggestion.d.ts.map +1 -0
- package/dist/components/frame/suggestion/suggestion.js +127 -0
- package/dist/components/frame/suggestion/suggestion.js.map +1 -0
- package/dist/components/frame/tabs/lt-tabs.d.ts +404 -0
- package/dist/components/frame/tabs/lt-tabs.d.ts.map +1 -0
- package/dist/components/frame/tabs/lt-tabs.js +1201 -0
- package/dist/components/frame/tabs/lt-tabs.js.map +1 -0
- package/dist/components/frame/tabs/tabs.d.ts +112 -0
- package/dist/components/frame/tabs/tabs.d.ts.map +1 -0
- package/dist/components/frame/tabs/tabs.js +107 -0
- package/dist/components/frame/tabs/tabs.js.map +1 -0
- package/dist/components/host-element.d.ts +135 -0
- package/dist/components/host-element.d.ts.map +1 -0
- package/dist/components/host-element.js +366 -0
- package/dist/components/host-element.js.map +1 -0
- package/dist/components/standalone/connection-status/connection-status.d.ts +28 -0
- package/dist/components/standalone/connection-status/connection-status.d.ts.map +1 -0
- package/dist/components/standalone/connection-status/connection-status.js +22 -0
- package/dist/components/standalone/connection-status/connection-status.js.map +1 -0
- package/dist/components/standalone/connection-status/lt-connection-status.d.ts +81 -0
- package/dist/components/standalone/connection-status/lt-connection-status.d.ts.map +1 -0
- package/dist/components/standalone/connection-status/lt-connection-status.js +216 -0
- package/dist/components/standalone/connection-status/lt-connection-status.js.map +1 -0
- package/dist/components/standalone/toast/lt-toast.d.ts +109 -0
- package/dist/components/standalone/toast/lt-toast.d.ts.map +1 -0
- package/dist/components/standalone/toast/lt-toast.js +256 -0
- package/dist/components/standalone/toast/lt-toast.js.map +1 -0
- package/dist/components/standalone/toast/toast.d.ts +52 -0
- package/dist/components/standalone/toast/toast.d.ts.map +1 -0
- package/dist/components/standalone/toast/toast.js +42 -0
- package/dist/components/standalone/toast/toast.js.map +1 -0
- package/dist/diagnostics/core.d.ts +137 -0
- package/dist/diagnostics/core.d.ts.map +1 -0
- package/dist/diagnostics/core.js +72 -0
- package/dist/diagnostics/core.js.map +1 -0
- package/dist/diagnostics/default-core.d.ts +10 -0
- package/dist/diagnostics/default-core.d.ts.map +1 -0
- package/dist/diagnostics/default-core.js +72 -0
- package/dist/diagnostics/default-core.js.map +1 -0
- package/dist/diagnostics/index.d.ts +84 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/diagnostics/index.js +106 -0
- package/dist/diagnostics/index.js.map +1 -0
- package/dist/dom.d.ts +55 -0
- package/dist/dom.d.ts.map +1 -0
- package/dist/dom.js +162 -0
- package/dist/dom.js.map +1 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx/react.d.ts +180 -0
- package/dist/jsx/react.d.ts.map +1 -0
- package/dist/jsx/react.js +2 -0
- package/dist/jsx/react.js.map +1 -0
- package/dist/lotek.css +3617 -0
- package/dist/lt.d.ts +325 -0
- package/dist/lt.d.ts.map +1 -0
- package/dist/lt.js +183 -0
- package/dist/lt.js.map +1 -0
- package/dist/react.d.ts +492 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +296 -0
- package/dist/react.js.map +1 -0
- package/dist/register.d.ts +17 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +35 -0
- package/dist/register.js.map +1 -0
- package/dist/tokens/color.d.ts +43 -0
- package/dist/tokens/color.d.ts.map +1 -0
- package/dist/tokens/color.js +123 -0
- package/dist/tokens/color.js.map +1 -0
- package/dist/tokens/contract.d.ts +18 -0
- package/dist/tokens/contract.d.ts.map +1 -0
- package/dist/tokens/contract.js +18 -0
- package/dist/tokens/contract.js.map +1 -0
- package/dist/tokens/matrix-cells.d.ts +30 -0
- package/dist/tokens/matrix-cells.d.ts.map +1 -0
- package/dist/tokens/matrix-cells.js +273 -0
- package/dist/tokens/matrix-cells.js.map +1 -0
- package/dist/tokens/matrix.d.ts +18 -0
- package/dist/tokens/matrix.d.ts.map +1 -0
- package/dist/tokens/matrix.js +21 -0
- package/dist/tokens/matrix.js.map +1 -0
- package/dist/tokens/theme-check.d.ts +42 -0
- package/dist/tokens/theme-check.d.ts.map +1 -0
- package/dist/tokens/theme-check.js +10 -0
- package/dist/tokens/theme-check.js.map +1 -0
- package/dist/tokens/theme.d.ts +94 -0
- package/dist/tokens/theme.d.ts.map +1 -0
- package/dist/tokens/theme.js +14 -0
- package/dist/tokens/theme.js.map +1 -0
- package/dist/tokens/tokens.d.ts +122 -0
- package/dist/tokens/tokens.d.ts.map +1 -0
- package/dist/tokens/tokens.js +158 -0
- package/dist/tokens/tokens.js.map +1 -0
- package/dist/vocabulary/classes.d.ts +3 -0
- package/dist/vocabulary/classes.d.ts.map +1 -0
- package/dist/vocabulary/classes.js +1320 -0
- package/dist/vocabulary/classes.js.map +1 -0
- package/dist/vocabulary/elements.d.ts +3 -0
- package/dist/vocabulary/elements.d.ts.map +1 -0
- package/dist/vocabulary/elements.js +410 -0
- package/dist/vocabulary/elements.js.map +1 -0
- package/dist/vocabulary/types.d.ts +175 -0
- package/dist/vocabulary/types.d.ts.map +1 -0
- package/dist/vocabulary/types.js +11 -0
- package/dist/vocabulary/types.js.map +1 -0
- package/dist/wasi-host.d.ts +24 -0
- package/dist/wasi-host.d.ts.map +1 -0
- package/dist/wasi-host.js +140 -0
- package/dist/wasi-host.js.map +1 -0
- package/live-templates.xml +62 -0
- package/manifest/files.json +373 -0
- package/manifest/manifest.json +4965 -0
- package/manifest/manifest.schema.json +513 -0
- package/package.json +398 -5
- package/src/cli.ts +21 -0
- package/src/components/css/accordion/accordion.css +102 -0
- package/src/components/css/accordion/accordion.ts +50 -0
- package/src/components/css/alert/alert.css +53 -0
- package/src/components/css/alert/alert.ts +48 -0
- package/src/components/css/avatar/avatar.css +96 -0
- package/src/components/css/avatar/avatar.ts +57 -0
- package/src/components/css/badge/badge.css +42 -0
- package/src/components/css/badge/badge.ts +43 -0
- package/src/components/css/breadcrumbs/breadcrumbs.css +62 -0
- package/src/components/css/breadcrumbs/breadcrumbs.ts +30 -0
- package/src/components/css/button/button.css +128 -0
- package/src/components/css/button/button.ts +44 -0
- package/src/components/css/card/card.css +65 -0
- package/src/components/css/card/card.ts +50 -0
- package/src/components/css/checkbox/checkbox.css +114 -0
- package/src/components/css/checkbox/checkbox.ts +50 -0
- package/src/components/css/divider/divider.css +38 -0
- package/src/components/css/divider/divider.ts +42 -0
- package/src/components/css/error-text/error-text.css +21 -0
- package/src/components/css/error-text/error-text.ts +37 -0
- package/src/components/css/fieldset/fieldset.css +72 -0
- package/src/components/css/fieldset/fieldset.ts +87 -0
- package/src/components/css/file-upload/file-upload.css +102 -0
- package/src/components/css/file-upload/file-upload.ts +65 -0
- package/src/components/css/heading/heading.css +33 -0
- package/src/components/css/heading/heading.ts +42 -0
- package/src/components/css/help-text/help-text.css +24 -0
- package/src/components/css/help-text/help-text.ts +42 -0
- package/src/components/css/icon/icon.css +20 -0
- package/src/components/css/icon/icon.ts +44 -0
- package/src/components/css/input/input.css +145 -0
- package/src/components/css/input/input.ts +77 -0
- package/src/components/css/label/label.css +42 -0
- package/src/components/css/label/label.ts +51 -0
- package/src/components/css/link/link.css +38 -0
- package/src/components/css/link/link.ts +38 -0
- package/src/components/css/list/list.css +53 -0
- package/src/components/css/list/list.ts +44 -0
- package/src/components/css/pagination/pagination.css +95 -0
- package/src/components/css/pagination/pagination.ts +33 -0
- package/src/components/css/paragraph/paragraph.css +31 -0
- package/src/components/css/paragraph/paragraph.ts +53 -0
- package/src/components/css/progress/progress.css +161 -0
- package/src/components/css/progress/progress.ts +78 -0
- package/src/components/css/radio/radio.css +94 -0
- package/src/components/css/radio/radio.ts +50 -0
- package/src/components/css/search/search.css +50 -0
- package/src/components/css/search/search.ts +56 -0
- package/src/components/css/select/select.css +321 -0
- package/src/components/css/select/select.ts +63 -0
- package/src/components/css/shared.ts +199 -0
- package/src/components/css/skeleton/skeleton.css +62 -0
- package/src/components/css/skeleton/skeleton.ts +43 -0
- package/src/components/css/skip-link/skip-link.css +41 -0
- package/src/components/css/skip-link/skip-link.ts +22 -0
- package/src/components/css/spinner/spinner.css +48 -0
- package/src/components/css/spinner/spinner.ts +48 -0
- package/src/components/css/sr-only/sr-only.css +16 -0
- package/src/components/css/sr-only/sr-only.ts +21 -0
- package/src/components/css/switch/switch.css +105 -0
- package/src/components/css/switch/switch.ts +50 -0
- package/src/components/css/table/table.css +159 -0
- package/src/components/css/table/table.ts +107 -0
- package/src/components/css/tag/tag.css +58 -0
- package/src/components/css/tag/tag.ts +49 -0
- package/src/components/css/textarea/textarea.css +83 -0
- package/src/components/css/textarea/textarea.ts +40 -0
- package/src/components/css/toggle-group/toggle-group.css +92 -0
- package/src/components/css/toggle-group/toggle-group.ts +37 -0
- package/src/components/css/tooltip/tooltip.css +89 -0
- package/src/components/css/tooltip/tooltip.ts +37 -0
- package/src/components/default-texts.ts +34 -0
- package/src/components/events.ts +68 -0
- package/src/components/frame/dialog/dialog.css +306 -0
- package/src/components/frame/dialog/dialog.ts +166 -0
- package/src/components/frame/dialog/lt-dialog.ts +510 -0
- package/src/components/frame/error-summary/error-summary.css +47 -0
- package/src/components/frame/error-summary/error-summary.ts +56 -0
- package/src/components/frame/error-summary/lt-error-summary.ts +344 -0
- package/src/components/frame/field/field-core.ts +152 -0
- package/src/components/frame/field/field.css +17 -0
- package/src/components/frame/field/lt-field.ts +753 -0
- package/src/components/frame/popover/lt-popover.ts +555 -0
- package/src/components/frame/popover/popover.css +50 -0
- package/src/components/frame/popover/popover.ts +102 -0
- package/src/components/frame/session-timeout/lt-session-timeout.ts +681 -0
- package/src/components/frame/session-timeout/session-timeout.css +50 -0
- package/src/components/frame/session-timeout/session-timeout.ts +156 -0
- package/src/components/frame/suggestion/lt-suggestion.ts +1358 -0
- package/src/components/frame/suggestion/suggestion.css +132 -0
- package/src/components/frame/suggestion/suggestion.ts +172 -0
- package/src/components/frame/tabs/lt-tabs.ts +1319 -0
- package/src/components/frame/tabs/tabs.css +128 -0
- package/src/components/frame/tabs/tabs.ts +188 -0
- package/src/components/host-element.ts +400 -0
- package/src/components/standalone/connection-status/connection-status.css +41 -0
- package/src/components/standalone/connection-status/connection-status.ts +41 -0
- package/src/components/standalone/connection-status/lt-connection-status.ts +242 -0
- package/src/components/standalone/toast/lt-toast.ts +300 -0
- package/src/components/standalone/toast/toast.css +78 -0
- package/src/components/standalone/toast/toast.ts +70 -0
- package/src/diagnostics/core.ts +210 -0
- package/src/diagnostics/default-core.ts +81 -0
- package/src/diagnostics/index.ts +150 -0
- package/src/dom.ts +185 -0
- package/src/index.ts +218 -0
- package/src/jsx/react.ts +212 -0
- package/src/lt.ts +192 -0
- package/src/react.ts +411 -0
- package/src/register.ts +43 -0
- package/src/tailwind/tailwind.css +169 -0
- package/src/tokens/boundary.css +104 -0
- package/src/tokens/color-contract.json +231 -0
- package/src/tokens/color.ts +150 -0
- package/src/tokens/contract.ts +24 -0
- package/src/tokens/matrix-cells.ts +375 -0
- package/src/tokens/matrix.ts +32 -0
- package/src/tokens/theme-check.ts +51 -0
- package/src/tokens/theme.ts +104 -0
- package/src/tokens/tokens.css +569 -0
- package/src/tokens/tokens.ts +223 -0
- package/src/vocabulary/classes.ts +1322 -0
- package/src/vocabulary/elements.ts +412 -0
- package/src/vocabulary/types.ts +178 -0
- package/src/wasi-host.ts +155 -0
- package/web-types.json +800 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { attributes, createGuard } from "../shared.js"
|
|
2
|
+
|
|
3
|
+
export const SKELETON_CLASS = "lt-skeleton" as const
|
|
4
|
+
|
|
5
|
+
export const skeletonVariants = ["block", "text", "circle"] as const
|
|
6
|
+
|
|
7
|
+
export type SkeletonVariant = (typeof skeletonVariants)[number]
|
|
8
|
+
export type NonDefaultSkeletonVariant = Exclude<SkeletonVariant, "block">
|
|
9
|
+
|
|
10
|
+
export type SkeletonOptions = {
|
|
11
|
+
/** Shape. Default: `block`. */
|
|
12
|
+
variant?: SkeletonVariant
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type SkeletonAttributes = {
|
|
16
|
+
class: typeof SKELETON_CLASS
|
|
17
|
+
"data-variant"?: NonDefaultSkeletonVariant
|
|
18
|
+
"aria-hidden": "true"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The attributes for a placeholder while the content loads.
|
|
23
|
+
*
|
|
24
|
+
* The shapes are always hidden from screen readers. They say nothing about
|
|
25
|
+
* what is coming, and a row of empty boxes being announced is worse than
|
|
26
|
+
* silence. Announce the wait in one place instead, with `role="status"`.
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* <div {...skeleton({ variant: "text" })} />
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export const skeleton = Object.assign(
|
|
33
|
+
({ variant = "block" }: SkeletonOptions = {}): SkeletonAttributes =>
|
|
34
|
+
attributes({
|
|
35
|
+
class: SKELETON_CLASS,
|
|
36
|
+
"data-variant": variant === "block" ? undefined : variant,
|
|
37
|
+
"aria-hidden": "true" as const,
|
|
38
|
+
}),
|
|
39
|
+
{
|
|
40
|
+
variants: skeletonVariants,
|
|
41
|
+
isVariant: createGuard(skeletonVariants),
|
|
42
|
+
},
|
|
43
|
+
)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
@layer lotek {
|
|
2
|
+
/* The link sits off screen until it gets focus. It cannot be hidden with
|
|
3
|
+
display or visibility, because then the keyboard cannot reach it either,
|
|
4
|
+
and the whole point is lost. */
|
|
5
|
+
.lt-skip-link {
|
|
6
|
+
position: absolute;
|
|
7
|
+
inset-inline-start: var(--lt-spacing-2);
|
|
8
|
+
inset-block-start: var(--lt-spacing-2);
|
|
9
|
+
z-index: 100;
|
|
10
|
+
transform: translateY(calc(-100% - var(--lt-spacing-4)));
|
|
11
|
+
display: inline-block;
|
|
12
|
+
padding: var(
|
|
13
|
+
--lt-skip-link-padding,
|
|
14
|
+
var(--lt-spacing-2) var(--lt-spacing-4)
|
|
15
|
+
);
|
|
16
|
+
font-family: inherit;
|
|
17
|
+
font-size: var(--lt-font-size-m);
|
|
18
|
+
line-height: var(--lt-line-height-default);
|
|
19
|
+
color: var(--lt-color-accent-content);
|
|
20
|
+
background: var(--lt-color-accent-fill);
|
|
21
|
+
border-radius: var(--lt-skip-link-radius, var(--lt-spacing-1));
|
|
22
|
+
text-decoration: underline;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* `:focus` and not `:focus-visible`. Focus set from code after a mouse
|
|
26
|
+
click does not count as "visible focus", and the link would then stay
|
|
27
|
+
hidden for someone a script sends there. After a key press it counts as
|
|
28
|
+
visible, but it is the mouse click that decides. */
|
|
29
|
+
.lt-skip-link:focus {
|
|
30
|
+
transform: translateY(0);
|
|
31
|
+
outline: var(--lt-focus-ring);
|
|
32
|
+
outline-color: var(--lt-color-neutral-text-strong);
|
|
33
|
+
outline-offset: 2px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
37
|
+
.lt-skip-link {
|
|
38
|
+
transition: transform 120ms ease;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { attributes } from "../shared.js"
|
|
2
|
+
|
|
3
|
+
export const SKIP_LINK_CLASS = "lt-skip-link" as const
|
|
4
|
+
|
|
5
|
+
export type SkipLinkAttributes = {
|
|
6
|
+
class: typeof SKIP_LINK_CLASS
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The attributes for a skip-to-content link.
|
|
11
|
+
*
|
|
12
|
+
* The link must be the first element in `<body>`, and point to the id of the
|
|
13
|
+
* main content. It sits off screen until it gets focus, and therefore cannot
|
|
14
|
+
* be hidden with `display: none`: the keyboard could not reach it either,
|
|
15
|
+
* and the whole point is lost.
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* <a {...skipLink()} href="#main-content">Skip to main content</a>
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const skipLink = (): SkipLinkAttributes =>
|
|
22
|
+
attributes({ class: SKIP_LINK_CLASS })
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
@layer lotek {
|
|
2
|
+
.lt-spinner {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
display: inline-block;
|
|
5
|
+
inline-size: var(--lt-spinner-size, var(--lt-spacing-6));
|
|
6
|
+
block-size: var(--lt-spinner-size, var(--lt-spacing-6));
|
|
7
|
+
border: var(--lt-spinner-thickness, 2px) solid
|
|
8
|
+
var(--lt-color-neutral-surface);
|
|
9
|
+
border-block-start-color: var(--lt-color-accent-border);
|
|
10
|
+
border-radius: 50%;
|
|
11
|
+
animation: lt-spinner-rotate 800ms linear infinite;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.lt-spinner[data-size="small"] {
|
|
15
|
+
inline-size: var(--lt-spacing-4);
|
|
16
|
+
block-size: var(--lt-spacing-4);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.lt-spinner[data-size="large"] {
|
|
20
|
+
inline-size: var(--lt-spacing-10);
|
|
21
|
+
block-size: var(--lt-spacing-10);
|
|
22
|
+
border-width: 3px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@keyframes lt-spinner-rotate {
|
|
26
|
+
to {
|
|
27
|
+
transform: rotate(360deg);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* The user has asked for less motion. It then spins more slowly rather
|
|
32
|
+
than standing still: an indicator that does not move no longer says that
|
|
33
|
+
something is going on. */
|
|
34
|
+
@media (prefers-reduced-motion: reduce) {
|
|
35
|
+
.lt-spinner {
|
|
36
|
+
animation-duration: 2400ms;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* High contrast: all four borders are forced to the same colour, and the
|
|
41
|
+
ring becomes an even circle. It still spins, but `Highlight` brings back
|
|
42
|
+
the mark that shows something is happening. */
|
|
43
|
+
@media (forced-colors: active) {
|
|
44
|
+
.lt-spinner {
|
|
45
|
+
border-block-start-color: Highlight;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { attributes, createGuard } from "../shared.js"
|
|
2
|
+
|
|
3
|
+
export const SPINNER_CLASS = "lt-spinner" as const
|
|
4
|
+
|
|
5
|
+
export const spinnerSizes = ["small", "medium", "large"] as const
|
|
6
|
+
|
|
7
|
+
export type SpinnerSize = (typeof spinnerSizes)[number]
|
|
8
|
+
export type NonDefaultSpinnerSize = Exclude<SpinnerSize, "medium">
|
|
9
|
+
|
|
10
|
+
export type SpinnerOptions = {
|
|
11
|
+
/** Size. Default: `medium`. */
|
|
12
|
+
size?: SpinnerSize
|
|
13
|
+
/** What is loading. Becomes `aria-label`, so the ring has a name for screen readers. */
|
|
14
|
+
label?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type SpinnerAttributes = {
|
|
18
|
+
class: typeof SPINNER_CLASS
|
|
19
|
+
"data-size"?: NonDefaultSpinnerSize
|
|
20
|
+
role?: "status"
|
|
21
|
+
"aria-label"?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The attributes for a loading indicator.
|
|
26
|
+
*
|
|
27
|
+
* Without `label` the ring is only a shape, and screen readers announce
|
|
28
|
+
* nothing. With `label` it becomes a `role="status"` that says what is going
|
|
29
|
+
* on. If you already have a visible text next to it, let that carry the
|
|
30
|
+
* message and drop `label`, so the same thing is not announced twice.
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* <span {...spinner({ label: "Loading applications" })} />
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export const spinner = Object.assign(
|
|
37
|
+
({ size = "medium", label }: SpinnerOptions = {}): SpinnerAttributes =>
|
|
38
|
+
attributes({
|
|
39
|
+
class: SPINNER_CLASS,
|
|
40
|
+
"data-size": size === "medium" ? undefined : size,
|
|
41
|
+
role: label ? ("status" as const) : undefined,
|
|
42
|
+
"aria-label": label,
|
|
43
|
+
}),
|
|
44
|
+
{
|
|
45
|
+
sizes: spinnerSizes,
|
|
46
|
+
isSize: createGuard(spinnerSizes),
|
|
47
|
+
},
|
|
48
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
@layer lotek {
|
|
2
|
+
/* Text that only screen readers should get. `display: none` and
|
|
3
|
+
`visibility: hidden` remove the element for them too, so the content must
|
|
4
|
+
stay in the document and be shrunk away visually instead. */
|
|
5
|
+
.lt-sr-only {
|
|
6
|
+
position: absolute;
|
|
7
|
+
width: 1px;
|
|
8
|
+
height: 1px;
|
|
9
|
+
padding: 0;
|
|
10
|
+
margin: -1px;
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
clip-path: inset(50%);
|
|
13
|
+
white-space: nowrap;
|
|
14
|
+
border-width: 0;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { attributes } from "../shared.js"
|
|
2
|
+
|
|
3
|
+
export const SR_ONLY_CLASS = "lt-sr-only" as const
|
|
4
|
+
|
|
5
|
+
export type SrOnlyAttributes = {
|
|
6
|
+
class: typeof SR_ONLY_CLASS
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The attributes for text that only screen readers should get.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* <span {...srOnly()}>Opens in a new tab</span>
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Use it when a label or explanation is needed by someone listening to the
|
|
17
|
+
* page, but would be noise to someone looking at it. If the content should
|
|
18
|
+
* be gone for everyone, use `hidden` instead.
|
|
19
|
+
*/
|
|
20
|
+
export const srOnly = (): SrOnlyAttributes =>
|
|
21
|
+
attributes({ class: SR_ONLY_CLASS })
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
@layer lotek {
|
|
2
|
+
.lt-switch {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
appearance: none;
|
|
5
|
+
flex: none;
|
|
6
|
+
display: inline-block;
|
|
7
|
+
inline-size: var(--lt-switch-width, var(--lt-spacing-10));
|
|
8
|
+
block-size: var(--lt-switch-height, var(--lt-spacing-6));
|
|
9
|
+
margin: 0;
|
|
10
|
+
border: 1px solid var(--lt-color-neutral-border);
|
|
11
|
+
border-radius: var(--lt-spacing-4);
|
|
12
|
+
background-color: var(--lt-color-neutral-surface);
|
|
13
|
+
/* The knob is a gradient, not a pseudo-element: Firefox does not render
|
|
14
|
+
::before and ::after on an <input>. */
|
|
15
|
+
background-image: radial-gradient(
|
|
16
|
+
circle at center,
|
|
17
|
+
var(--lt-color-neutral-text-strong) 0 34%,
|
|
18
|
+
transparent 36%
|
|
19
|
+
);
|
|
20
|
+
background-repeat: no-repeat;
|
|
21
|
+
background-size: var(--lt-switch-height, var(--lt-spacing-6)) 100%;
|
|
22
|
+
/* background-position has no logical variant, so both directions are
|
|
23
|
+
written by hand. Off is at the start, on is at the end. */
|
|
24
|
+
background-position: left center;
|
|
25
|
+
cursor: pointer;
|
|
26
|
+
transition:
|
|
27
|
+
background-color 120ms ease,
|
|
28
|
+
background-position 120ms ease;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Without `:not(:disabled)`. It raised the specificity above the states
|
|
32
|
+
below, so the mouse removed the border of a switch that was on. The
|
|
33
|
+
rules for checked and disabled come after this one and win on order. */
|
|
34
|
+
.lt-switch:hover {
|
|
35
|
+
border-color: var(--lt-color-neutral-border-strong);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.lt-switch:focus-visible {
|
|
39
|
+
outline: var(--lt-focus-ring);
|
|
40
|
+
outline-offset: 2px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.lt-switch:dir(rtl) {
|
|
44
|
+
background-position: right center;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.lt-switch:checked {
|
|
48
|
+
background-color: var(--lt-color-accent-fill);
|
|
49
|
+
border-color: var(--lt-color-accent-fill);
|
|
50
|
+
background-position: right center;
|
|
51
|
+
background-image: radial-gradient(
|
|
52
|
+
circle at center,
|
|
53
|
+
var(--lt-color-accent-content) 0 34%,
|
|
54
|
+
transparent 36%
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.lt-switch:checked:dir(rtl) {
|
|
59
|
+
background-position: left center;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.lt-switch:disabled {
|
|
63
|
+
background-color: var(--lt-color-disabled-surface);
|
|
64
|
+
border-color: var(--lt-color-disabled-surface);
|
|
65
|
+
background-image: radial-gradient(
|
|
66
|
+
circle at center,
|
|
67
|
+
var(--lt-color-disabled-text) 0 34%,
|
|
68
|
+
transparent 36%
|
|
69
|
+
);
|
|
70
|
+
cursor: not-allowed;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* The user has asked for less motion. The switch should still change
|
|
74
|
+
state, it just should not slide. */
|
|
75
|
+
@media (prefers-reduced-motion: reduce) {
|
|
76
|
+
.lt-switch {
|
|
77
|
+
transition: none;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.lt-switch-row {
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
gap: var(--lt-spacing-2);
|
|
85
|
+
line-height: var(--lt-line-height-default);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/*
|
|
89
|
+
* High contrast: the knob is a gradient, and disappears in the mode.
|
|
90
|
+
* Without it on and off look exactly alike. Here we fall back to a plain
|
|
91
|
+
* checkbox. The switch loses its shape, but `role="switch"` is still
|
|
92
|
+
* there, so it is announced as on and off, and the state is visible
|
|
93
|
+
* again.
|
|
94
|
+
*/
|
|
95
|
+
@media (forced-colors: active) {
|
|
96
|
+
.lt-switch,
|
|
97
|
+
.lt-switch:checked {
|
|
98
|
+
appearance: auto;
|
|
99
|
+
inline-size: auto;
|
|
100
|
+
block-size: auto;
|
|
101
|
+
background-image: none;
|
|
102
|
+
border: 0;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { attributes } from "../shared.js"
|
|
2
|
+
|
|
3
|
+
export const SWITCH_CLASS = "lt-switch" as const
|
|
4
|
+
/** The row that holds the switch and the text next to each other. */
|
|
5
|
+
export const SWITCH_ROW_CLASS = "lt-switch-row" as const
|
|
6
|
+
|
|
7
|
+
export type SwitchOptions = {
|
|
8
|
+
/**
|
|
9
|
+
* The control is disabled. Do not use it to lock the switch while a save
|
|
10
|
+
* is in progress: `disabled` takes focus away from it, and focus does not
|
|
11
|
+
* come back.
|
|
12
|
+
*/
|
|
13
|
+
disabled?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type SwitchAttributes = {
|
|
17
|
+
class: typeof SWITCH_CLASS
|
|
18
|
+
type: "checkbox"
|
|
19
|
+
role: "switch"
|
|
20
|
+
disabled?: true
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The attributes for an on/off switch.
|
|
25
|
+
*
|
|
26
|
+
* The switch is a checkbox with `role="switch"`. Screen readers then
|
|
27
|
+
* announce it as "on" and "off" rather than "checked", while the keyboard
|
|
28
|
+
* and `FormData` work as for a plain checkbox.
|
|
29
|
+
*
|
|
30
|
+
* The switch has no validation state. A choice that is on or off cannot be
|
|
31
|
+
* invalid in itself; if turning it on is required, the requirement belongs
|
|
32
|
+
* in a checkbox with `required`.
|
|
33
|
+
*
|
|
34
|
+
* ```ts
|
|
35
|
+
* <input {...switchControl()} />
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export const switchControl = Object.assign(
|
|
39
|
+
({ disabled }: SwitchOptions = {}): SwitchAttributes =>
|
|
40
|
+
attributes({
|
|
41
|
+
class: SWITCH_CLASS,
|
|
42
|
+
type: "checkbox" as const,
|
|
43
|
+
role: "switch" as const,
|
|
44
|
+
disabled: disabled ? (true as const) : undefined,
|
|
45
|
+
}),
|
|
46
|
+
{
|
|
47
|
+
/** The class on the row around the switch and the text. */
|
|
48
|
+
row: SWITCH_ROW_CLASS,
|
|
49
|
+
},
|
|
50
|
+
)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
@layer lotek {
|
|
2
|
+
.lt-table {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
inline-size: 100%;
|
|
5
|
+
border-collapse: collapse;
|
|
6
|
+
font-family: inherit;
|
|
7
|
+
font-size: var(--lt-font-size-m);
|
|
8
|
+
line-height: var(--lt-line-height-default);
|
|
9
|
+
color: var(--lt-color-neutral-text-strong);
|
|
10
|
+
/* Numbers stacked under each other must have the same width per digit,
|
|
11
|
+
or the column cannot be read downwards. */
|
|
12
|
+
font-variant-numeric: tabular-nums;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.lt-table caption {
|
|
16
|
+
text-align: start;
|
|
17
|
+
font-weight: var(--lt-font-weight-semibold);
|
|
18
|
+
padding-block-end: var(--lt-spacing-2);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.lt-table th,
|
|
22
|
+
.lt-table td {
|
|
23
|
+
padding: var(
|
|
24
|
+
--lt-table-cell-padding,
|
|
25
|
+
var(--lt-spacing-2) var(--lt-spacing-3)
|
|
26
|
+
);
|
|
27
|
+
text-align: start;
|
|
28
|
+
vertical-align: top;
|
|
29
|
+
border-block-end: 1px solid var(--lt-color-neutral-border-subtle);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.lt-table thead th {
|
|
33
|
+
font-weight: var(--lt-font-weight-semibold);
|
|
34
|
+
border-block-end: 2px solid var(--lt-color-neutral-border-strong);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.lt-table tbody tr:last-child th,
|
|
38
|
+
.lt-table tbody tr:last-child td {
|
|
39
|
+
border-block-end: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.lt-table[data-variant="striped"] tbody tr:nth-child(even) {
|
|
43
|
+
background: var(--lt-color-neutral-surface);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.lt-table[data-hoverable] tbody tr:hover {
|
|
47
|
+
background: var(--lt-color-accent-surface);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.lt-table td[data-align="end"],
|
|
51
|
+
.lt-table th[data-align="end"] {
|
|
52
|
+
text-align: end;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/*
|
|
56
|
+
* A sortable column has a button in the header, and the button fills the
|
|
57
|
+
* cell. The cell gives up its padding and the button takes it over, so
|
|
58
|
+
* the text sits where it would without a button and the whole cell can be
|
|
59
|
+
* pressed. Without that the header got padding from both the cell and the
|
|
60
|
+
* button, and became taller and shifted against the cells below.
|
|
61
|
+
*/
|
|
62
|
+
.lt-table th:has(> .lt-table__sort) {
|
|
63
|
+
padding: 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.lt-table__sort {
|
|
67
|
+
box-sizing: border-box;
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
gap: var(--lt-spacing-2);
|
|
71
|
+
inline-size: 100%;
|
|
72
|
+
margin: 0;
|
|
73
|
+
padding: var(
|
|
74
|
+
--lt-table-cell-padding,
|
|
75
|
+
var(--lt-spacing-2) var(--lt-spacing-3)
|
|
76
|
+
);
|
|
77
|
+
font: inherit;
|
|
78
|
+
color: inherit;
|
|
79
|
+
text-align: inherit;
|
|
80
|
+
background: none;
|
|
81
|
+
border: 0;
|
|
82
|
+
border-radius: 0;
|
|
83
|
+
/* Can also be a link, when the server sorts without JavaScript. */
|
|
84
|
+
text-decoration: none;
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.lt-table th[data-align="end"] > .lt-table__sort {
|
|
89
|
+
justify-content: flex-end;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.lt-table__sort:hover {
|
|
93
|
+
background: var(--lt-color-neutral-surface);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.lt-table__sort:focus-visible {
|
|
97
|
+
outline: var(--lt-focus-ring);
|
|
98
|
+
outline-offset: -2px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
* The arrow is read from `aria-sort` on the cell, not from a class. It is
|
|
103
|
+
* the same attribute the screen reader reads, so what is shown and what is
|
|
104
|
+
* said cannot drift apart. Without the attribute the button shows both
|
|
105
|
+
* arrows, muted, so it is visible that the column can be sorted.
|
|
106
|
+
*
|
|
107
|
+
* The arrow is a mask and not an image, so it takes the text colour and
|
|
108
|
+
* flips with the theme. An empty `content` means it never becomes part of
|
|
109
|
+
* the button's name.
|
|
110
|
+
*/
|
|
111
|
+
.lt-table__sort::after {
|
|
112
|
+
content: "";
|
|
113
|
+
flex: none;
|
|
114
|
+
inline-size: var(--lt-spacing-3);
|
|
115
|
+
block-size: var(--lt-spacing-3);
|
|
116
|
+
background-color: var(--lt-color-neutral-text-subtle);
|
|
117
|
+
mask:
|
|
118
|
+
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 1 13 6.5H3zM8 15 3 9.5H13z'/%3E%3C/svg%3E")
|
|
119
|
+
center / contain no-repeat;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.lt-table th[aria-sort="ascending"] > .lt-table__sort::after {
|
|
123
|
+
background-color: currentColor;
|
|
124
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 3 14 11H2z'/%3E%3C/svg%3E");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.lt-table th[aria-sort="descending"] > .lt-table__sort::after {
|
|
128
|
+
background-color: currentColor;
|
|
129
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 13 2 5H14z'/%3E%3C/svg%3E");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* High contrast: the mode forces the background colour to the surface
|
|
133
|
+
colour, and the arrow would then have become invisible. A system colour
|
|
134
|
+
is left alone, so it is drawn in the system text colour. */
|
|
135
|
+
@media (forced-colors: active) {
|
|
136
|
+
.lt-table__sort::after,
|
|
137
|
+
.lt-table th[aria-sort] > .lt-table__sort::after {
|
|
138
|
+
background-color: CanvasText;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* The arrow comes before the text in a right-aligned column, so the text
|
|
143
|
+
ends where the numbers below end. */
|
|
144
|
+
.lt-table th[data-align="end"] > .lt-table__sort::after {
|
|
145
|
+
order: -1;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* A table wider than the screen must be scrollable, and that area must be
|
|
149
|
+
reachable with the keyboard. Hence tabindex="0" on the container. */
|
|
150
|
+
.lt-table-scroll {
|
|
151
|
+
overflow-x: auto;
|
|
152
|
+
max-inline-size: 100%;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.lt-table-scroll:focus-visible {
|
|
156
|
+
outline: var(--lt-focus-ring);
|
|
157
|
+
outline-offset: 2px;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { attributes, createGuard } from "../shared.js"
|
|
2
|
+
|
|
3
|
+
export const TABLE_CLASS = "lt-table" as const
|
|
4
|
+
/** The container that lets a wide table scroll sideways. */
|
|
5
|
+
export const TABLE_SCROLL_CLASS = "lt-table-scroll" as const
|
|
6
|
+
|
|
7
|
+
export const tableVariants = ["default", "striped"] as const
|
|
8
|
+
|
|
9
|
+
export type TableVariant = (typeof tableVariants)[number]
|
|
10
|
+
export type NonDefaultTableVariant = Exclude<TableVariant, "default">
|
|
11
|
+
|
|
12
|
+
export type TableOptions = {
|
|
13
|
+
/** Every other row on a muted surface. Default: `default`. */
|
|
14
|
+
variant?: TableVariant
|
|
15
|
+
/** Highlights the row under the mouse. Use only when rows can be pressed. */
|
|
16
|
+
hoverable?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type TableAttributes = {
|
|
20
|
+
class: typeof TABLE_CLASS
|
|
21
|
+
"data-variant"?: NonDefaultTableVariant
|
|
22
|
+
"data-hoverable"?: ""
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The attributes for a table.
|
|
27
|
+
*
|
|
28
|
+
* The class goes on a real `<table>` with `<thead>` and `<th>`. The header
|
|
29
|
+
* cells are what let screen readers say "Amount, 1,240 kroner" when the user
|
|
30
|
+
* is in a cell. Build the table from `<div>` elements, and that connection
|
|
31
|
+
* does not exist.
|
|
32
|
+
*
|
|
33
|
+
* ```ts
|
|
34
|
+
* <table {...table({ variant: "striped" })}>…</table>
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export const table = Object.assign(
|
|
38
|
+
({ variant = "default", hoverable }: TableOptions = {}): TableAttributes =>
|
|
39
|
+
attributes({
|
|
40
|
+
class: TABLE_CLASS,
|
|
41
|
+
"data-variant": variant === "default" ? undefined : variant,
|
|
42
|
+
"data-hoverable": hoverable ? ("" as const) : undefined,
|
|
43
|
+
}),
|
|
44
|
+
{
|
|
45
|
+
/** The class on the container around a wide table. */
|
|
46
|
+
scroll: TABLE_SCROLL_CLASS,
|
|
47
|
+
variants: tableVariants,
|
|
48
|
+
isVariant: createGuard(tableVariants),
|
|
49
|
+
},
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
/** The class on the button in a sortable column header. */
|
|
53
|
+
export const TABLE_SORT_CLASS = "lt-table__sort" as const
|
|
54
|
+
|
|
55
|
+
export const tableSortDirections = ["ascending", "descending"] as const
|
|
56
|
+
|
|
57
|
+
export type TableSortDirection = (typeof tableSortDirections)[number]
|
|
58
|
+
|
|
59
|
+
export type TableSortOptions = {
|
|
60
|
+
/**
|
|
61
|
+
* The direction the column is sorted in. Left out, it means the table is
|
|
62
|
+
* not sorted by this column, and the header gets no `aria-sort`.
|
|
63
|
+
*/
|
|
64
|
+
direction?: TableSortDirection
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type TableSortAttributes = {
|
|
68
|
+
header: {
|
|
69
|
+
"aria-sort"?: TableSortDirection
|
|
70
|
+
}
|
|
71
|
+
button: {
|
|
72
|
+
class: typeof TABLE_SORT_CLASS
|
|
73
|
+
type: "button"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The attributes for a sortable column header.
|
|
79
|
+
*
|
|
80
|
+
* `aria-sort` is on the `<th>`, not on the button, because the cell is what
|
|
81
|
+
* describes the column. Only the sorted column has the attribute. The arrow
|
|
82
|
+
* is drawn from the same attribute, so what the screen reader says and what
|
|
83
|
+
* is shown cannot drift apart. The sorting itself is the app's job.
|
|
84
|
+
*
|
|
85
|
+
* ```ts
|
|
86
|
+
* const date = lt.tableSort({ direction: "descending" })
|
|
87
|
+
* ```
|
|
88
|
+
* ```html
|
|
89
|
+
* <th scope="col" {...date.header}>
|
|
90
|
+
* <button {...date.button}>Date</button>
|
|
91
|
+
* </th>
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export const tableSort = Object.assign(
|
|
95
|
+
({ direction }: TableSortOptions = {}): TableSortAttributes => ({
|
|
96
|
+
header: attributes({ "aria-sort": direction }),
|
|
97
|
+
button: attributes({ class: TABLE_SORT_CLASS, type: "button" as const }),
|
|
98
|
+
}),
|
|
99
|
+
{
|
|
100
|
+
// The list sits next to it, as `tableSortDirections`, and not on the
|
|
101
|
+
// function. The guard for the lists requires the attribute and the class
|
|
102
|
+
// to be on the same element, and here `aria-sort` is on the cell and the
|
|
103
|
+
// class on the button. The table test requires each direction to give its
|
|
104
|
+
// own arrow.
|
|
105
|
+
isDirection: createGuard(tableSortDirections),
|
|
106
|
+
},
|
|
107
|
+
)
|