@threadlabs/looma 0.32.1 → 0.33.1
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/README.md +15 -0
- package/bin/looma-docs.mjs +3 -0
- package/components/shared/icons.js +1 -0
- package/components/shared/overlay.js +1 -1
- package/components/ui-action-bar/ui-action-bar.html +11 -11
- package/components/ui-affordance-scope/ui-affordance-scope.html +2 -2
- package/components/ui-avatar/ui-avatar.html +8 -8
- package/components/ui-avatar-group/ui-avatar-group.html +14 -14
- package/components/ui-avatar-group/ui-avatar-group.js +3 -2
- package/components/ui-badge/ui-badge.html +43 -43
- package/components/ui-breadcrumb-item/ui-breadcrumb-item.html +13 -13
- package/components/ui-breadcrumbs/ui-breadcrumbs.html +8 -8
- package/components/ui-button/ui-button.html +32 -29
- package/components/ui-callout/ui-callout.html +9 -9
- package/components/ui-card/ui-card.html +11 -11
- package/components/ui-checkbox/ui-checkbox.html +52 -33
- package/components/ui-cluster/ui-cluster.html +21 -21
- package/components/ui-color-picker/ui-color-picker.html +135 -0
- package/components/ui-color-picker/ui-color-picker.js +76 -0
- package/components/ui-combobox/ui-combobox.html +43 -43
- package/components/ui-container/ui-container.html +7 -7
- package/components/ui-context-menu/ui-context-menu.html +9 -9
- package/components/ui-cover/ui-cover.html +8 -8
- package/components/ui-description-item/ui-description-item.html +7 -7
- package/components/ui-description-list/ui-description-list.html +4 -4
- package/components/ui-dialog/ui-dialog.html +26 -26
- package/components/ui-disclosure/ui-disclosure.html +23 -23
- package/components/ui-editable/ui-editable.html +16 -16
- package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html +9 -9
- package/components/ui-editor-link-form/ui-editor-link-form.html +1 -2
- package/components/ui-editor-mention-menu/ui-editor-mention-menu.html +23 -23
- package/components/ui-editor-mention-menu-item/ui-editor-mention-menu-item.html +10 -10
- package/components/ui-editor-slash-menu/ui-editor-slash-menu.html +29 -29
- package/components/ui-editor-slash-menu-group/ui-editor-slash-menu-group.html +5 -5
- package/components/ui-editor-slash-menu-item/ui-editor-slash-menu-item.html +11 -11
- package/components/ui-editor-surface/ui-editor-surface.html +2 -2
- package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +25 -25
- package/components/ui-editor-table-overlay/ui-editor-table-overlay.html +13 -13
- package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +31 -31
- package/components/ui-editor-toolbar/ui-editor-toolbar.html +13 -13
- package/components/ui-floating-action-button/ui-floating-action-button.html +8 -8
- package/components/ui-form-field/ui-form-field.html +15 -15
- package/components/ui-form-field/ui-form-field.js +12 -4
- package/components/ui-grid/ui-grid.html +4 -4
- package/components/ui-icon/ui-icon.html +3 -2
- package/components/ui-icon-button/ui-icon-button.html +15 -14
- package/components/ui-image/ui-image.html +14 -14
- package/components/ui-input/ui-input.html +8 -8
- package/components/ui-input-group/ui-input-group.html +18 -18
- package/components/ui-list/ui-list.html +11 -11
- package/components/ui-list-item/ui-list-item.html +18 -18
- package/components/ui-listbox/ui-listbox.html +10 -10
- package/components/ui-menu/ui-menu.html +18 -17
- package/components/ui-menu-group/ui-menu-group.html +4 -4
- package/components/ui-menu-item/ui-menu-item.html +20 -20
- package/components/ui-meter/ui-meter.html +5 -5
- package/components/ui-nav-item/ui-nav-item.html +20 -20
- package/components/ui-page-header/ui-page-header.html +18 -17
- package/components/ui-popover/ui-popover.html +8 -8
- package/components/ui-radio/ui-radio.html +25 -17
- package/components/ui-radio-group/ui-radio-group.html +10 -10
- package/components/ui-reel/ui-reel.html +5 -5
- package/components/ui-scroll-area/ui-scroll-area.html +10 -10
- package/components/ui-search-result-row/ui-search-result-row.html +19 -19
- package/components/ui-search-shell/ui-search-shell.html +22 -22
- package/components/ui-section/ui-section.html +24 -23
- package/components/ui-select/ui-select.html +10 -10
- package/components/ui-separator/ui-separator.html +2 -2
- package/components/ui-sidebar/ui-sidebar.html +8 -8
- package/components/ui-spinner/ui-spinner.html +6 -6
- package/components/ui-stack/ui-stack.html +12 -12
- package/components/ui-status-message/ui-status-message.html +17 -17
- package/components/ui-swatch/ui-swatch.html +2 -2
- package/components/ui-switch/ui-switch.html +36 -26
- package/components/ui-switcher/ui-switcher.html +7 -7
- package/components/ui-table/ui-table.html +6 -6
- package/components/ui-tabs/ui-tabs.html +16 -15
- package/components/ui-text/ui-text.html +3 -2
- package/components/ui-textarea/ui-textarea.html +10 -10
- package/components/ui-toast/ui-toast.html +9 -9
- package/components/ui-toast-region/ui-toast-region.html +12 -12
- package/components/ui-tooltip/ui-tooltip.html +15 -15
- package/components/ui-top-bar/ui-top-bar.html +11 -11
- package/components/ui-tree/ui-tree.html +5 -5
- package/components/ui-tree-item/ui-tree-item.html +36 -36
- package/dist/index.js +46 -45
- package/docs/README.md +116 -0
- package/docs/card.html +63 -0
- package/docs/card.js +32 -0
- package/docs/catalog-view.js +18 -0
- package/docs/catalog-view.mjs +11 -0
- package/docs/catalog.json +22974 -0
- package/docs/catalog.mjs +131 -0
- package/docs/cli.mjs +26 -0
- package/docs/commands.mjs +94 -0
- package/docs/customizer-render.mjs +40 -0
- package/docs/customizer.js +118 -0
- package/docs/documentation.css +8 -0
- package/docs/examples/ui-action-bar/examples/01-form-footer.behavior.js +7 -0
- package/docs/examples/ui-button/examples/08-loading.behavior.js +21 -0
- package/docs/examples/ui-checkbox/examples/02-checked-indeterminate-and-disabled.behavior.js +30 -0
- package/docs/examples/ui-combobox/examples/06-selected-values.behavior.js +11 -0
- package/docs/examples/ui-search-shell/examples/02-label-dismissible-status-and-footer.behavior.js +34 -0
- package/docs/examples/ui-toast/examples/01-authored.behavior.js +15 -0
- package/docs/examples/ui-toast/examples/02-danger.behavior.js +2 -0
- package/docs/examples/ui-tree/examples/03-max-depth-2-and-hover-expand-delay-300.behavior.js +30 -0
- package/docs/examples/ui-tree/examples/06-move-without-dragging.behavior.js +2 -0
- package/docs/examples/ui-tree/examples/07-multiple-selection.behavior.js +16 -0
- package/docs/examples/ui-tree-item/examples/02-container.behavior.js +1 -0
- package/docs/index.d.ts +54 -0
- package/docs/index.mjs +4 -0
- package/docs/local-server.mjs +68 -0
- package/docs/preview.js +20 -0
- package/docs/reference.html +1 -0
- package/docs/reference.js +36 -0
- package/docs/render.mjs +84 -0
- package/docs/site.mjs +198 -0
- package/docs/store.mjs +92 -0
- package/docs/theme.mjs +100 -0
- package/docs/workspace.mjs +32 -0
- package/package.json +28 -3
- package/styles/ui-action-bar.css +11 -11
- package/styles/ui-affordance-scope.css +2 -2
- package/styles/ui-avatar-group.css +14 -14
- package/styles/ui-avatar.css +8 -8
- package/styles/ui-badge.css +41 -41
- package/styles/ui-breadcrumb-item.css +13 -13
- package/styles/ui-breadcrumbs.css +8 -8
- package/styles/ui-button.css +30 -28
- package/styles/ui-callout.css +9 -9
- package/styles/ui-card.css +11 -11
- package/styles/ui-checkbox.css +52 -33
- package/styles/ui-cluster.css +21 -21
- package/styles/ui-color-picker.css +120 -0
- package/styles/ui-combobox.css +86 -86
- package/styles/ui-container.css +7 -7
- package/styles/ui-context-menu.css +9 -9
- package/styles/ui-cover.css +8 -8
- package/styles/ui-description-item.css +7 -7
- package/styles/ui-description-list.css +4 -4
- package/styles/ui-dialog.css +52 -52
- package/styles/ui-disclosure.css +23 -23
- package/styles/ui-editable.css +16 -16
- package/styles/ui-editor-insert-table-grid.css +9 -9
- package/styles/ui-editor-mention-menu-item.css +10 -10
- package/styles/ui-editor-mention-menu.css +23 -23
- package/styles/ui-editor-slash-menu-group.css +5 -5
- package/styles/ui-editor-slash-menu-item.css +11 -11
- package/styles/ui-editor-slash-menu.css +29 -29
- package/styles/ui-editor-surface.css +2 -2
- package/styles/ui-editor-table-context-menu.css +25 -25
- package/styles/ui-editor-table-overlay.css +13 -13
- package/styles/ui-editor-table-toolbar.css +31 -31
- package/styles/ui-editor-toolbar.css +13 -13
- package/styles/ui-floating-action-button.css +8 -8
- package/styles/ui-form-field.css +13 -13
- package/styles/ui-grid.css +4 -4
- package/styles/ui-icon-button.css +13 -13
- package/styles/ui-icon.css +2 -2
- package/styles/ui-image.css +14 -14
- package/styles/ui-input-group.css +18 -18
- package/styles/ui-input.css +8 -8
- package/styles/ui-list-item.css +18 -18
- package/styles/ui-list.css +11 -11
- package/styles/ui-listbox.css +20 -20
- package/styles/ui-menu-group.css +4 -4
- package/styles/ui-menu-item.css +20 -20
- package/styles/ui-menu.css +16 -16
- package/styles/ui-meter.css +5 -5
- package/styles/ui-nav-item.css +20 -20
- package/styles/ui-page-header.css +18 -17
- package/styles/ui-popover.css +8 -8
- package/styles/ui-radio-group.css +10 -10
- package/styles/ui-radio.css +26 -18
- package/styles/ui-reel.css +5 -5
- package/styles/ui-scroll-area.css +10 -10
- package/styles/ui-search-result-row.css +19 -19
- package/styles/ui-search-shell.css +22 -22
- package/styles/ui-section.css +24 -23
- package/styles/ui-select.css +10 -10
- package/styles/ui-separator.css +2 -2
- package/styles/ui-sidebar.css +8 -8
- package/styles/ui-spinner.css +6 -6
- package/styles/ui-stack.css +12 -12
- package/styles/ui-status-message.css +17 -17
- package/styles/ui-swatch.css +2 -2
- package/styles/ui-switch.css +36 -28
- package/styles/ui-switcher.css +7 -7
- package/styles/ui-table.css +6 -6
- package/styles/ui-tabs.css +11 -11
- package/styles/ui-text.css +3 -2
- package/styles/ui-textarea.css +10 -10
- package/styles/ui-toast-region.css +24 -24
- package/styles/ui-toast.css +18 -18
- package/styles/ui-tooltip.css +15 -15
- package/styles/ui-top-bar.css +11 -11
- package/styles/ui-tree-item.css +71 -71
- package/styles/ui-tree.css +5 -5
- package/theme-system.css +80 -0
- package/tokens.css +14 -3
- package/vanilla/UiColorPicker.d.ts +30 -0
- package/vanilla/UiColorPicker.js +77 -0
- package/vanilla/UiIcon.js +1 -1
- package/vanilla/index.js +1 -0
- package/vue/UiActionBar.vue +11 -11
- package/vue/UiAffordanceScope.vue +2 -2
- package/vue/UiAvatar.vue +8 -8
- package/vue/UiAvatarGroup.vue +14 -14
- package/vue/UiBadge.vue +43 -42
- package/vue/UiBreadcrumbItem.vue +13 -13
- package/vue/UiBreadcrumbs.vue +8 -8
- package/vue/UiButton.vue +34 -29
- package/vue/UiCallout.vue +9 -9
- package/vue/UiCard.vue +11 -11
- package/vue/UiCheckbox.vue +57 -34
- package/vue/UiCluster.vue +21 -21
- package/vue/UiColorPicker.d.ts +65 -0
- package/vue/UiColorPicker.js +2 -0
- package/vue/UiColorPicker.vue +422 -0
- package/vue/UiCombobox.vue +86 -86
- package/vue/UiContainer.vue +7 -7
- package/vue/UiContextMenu.vue +9 -9
- package/vue/UiCover.vue +8 -8
- package/vue/UiDescriptionItem.vue +7 -7
- package/vue/UiDescriptionList.vue +4 -4
- package/vue/UiDialog.vue +52 -52
- package/vue/UiDisclosure.vue +23 -23
- package/vue/UiEditable.vue +16 -16
- package/vue/UiEditorInsertTableGrid.vue +9 -9
- package/vue/UiEditorMentionMenu.vue +23 -23
- package/vue/UiEditorMentionMenuItem.vue +10 -10
- package/vue/UiEditorSlashMenu.vue +29 -29
- package/vue/UiEditorSlashMenuGroup.vue +5 -5
- package/vue/UiEditorSlashMenuItem.vue +11 -11
- package/vue/UiEditorSurface.vue +2 -2
- package/vue/UiEditorTableContextMenu.vue +25 -25
- package/vue/UiEditorTableOverlay.vue +13 -13
- package/vue/UiEditorTableToolbar.vue +31 -31
- package/vue/UiEditorToolbar.vue +13 -13
- package/vue/UiFloatingActionButton.vue +8 -8
- package/vue/UiFormField.vue +14 -14
- package/vue/UiGrid.vue +4 -4
- package/vue/UiIcon.vue +6 -2
- package/vue/UiIconButton.vue +14 -14
- package/vue/UiImage.vue +14 -14
- package/vue/UiInput.vue +9 -8
- package/vue/UiInputGroup.vue +18 -18
- package/vue/UiList.vue +11 -11
- package/vue/UiListItem.vue +18 -18
- package/vue/UiListbox.vue +20 -20
- package/vue/UiMenu.vue +16 -16
- package/vue/UiMenuGroup.vue +4 -4
- package/vue/UiMenuItem.vue +20 -20
- package/vue/UiMeter.vue +5 -5
- package/vue/UiNavItem.vue +20 -20
- package/vue/UiPageHeader.vue +18 -17
- package/vue/UiPopover.vue +8 -8
- package/vue/UiRadio.vue +28 -17
- package/vue/UiRadioGroup.vue +10 -10
- package/vue/UiReel.vue +5 -5
- package/vue/UiScrollArea.vue +10 -10
- package/vue/UiSearchResultRow.vue +19 -19
- package/vue/UiSearchShell.vue +22 -22
- package/vue/UiSection.vue +24 -23
- package/vue/UiSelect.vue +11 -10
- package/vue/UiSeparator.vue +2 -2
- package/vue/UiSidebar.vue +8 -8
- package/vue/UiSpinner.vue +6 -6
- package/vue/UiStack.vue +12 -12
- package/vue/UiStatusMessage.vue +17 -17
- package/vue/UiSwatch.vue +2 -2
- package/vue/UiSwitch.vue +38 -25
- package/vue/UiSwitcher.vue +7 -7
- package/vue/UiTable.vue +6 -6
- package/vue/UiTabs.vue +13 -13
- package/vue/UiText.vue +3 -2
- package/vue/UiTextarea.vue +10 -10
- package/vue/UiToast.vue +18 -18
- package/vue/UiToastRegion.vue +24 -24
- package/vue/UiTooltip.vue +15 -15
- package/vue/UiTopBar.vue +11 -11
- package/vue/UiTree.vue +5 -5
- package/vue/UiTreeItem.vue +73 -71
- package/vue/chunks/UiActionBar.js +1 -1
- package/vue/chunks/UiAffordanceScope.js +1 -1
- package/vue/chunks/UiAvatar.js +1 -1
- package/vue/chunks/UiAvatarGroup.js +1 -1
- package/vue/chunks/UiBadge.js +2 -2
- package/vue/chunks/UiBreadcrumbItem.js +1 -1
- package/vue/chunks/UiBreadcrumbs.js +1 -1
- package/vue/chunks/UiButton.js +2 -2
- package/vue/chunks/UiCallout.js +1 -1
- package/vue/chunks/UiCard.js +1 -1
- package/vue/chunks/UiCheckbox.js +1 -1
- package/vue/chunks/UiCluster.js +1 -1
- package/vue/chunks/UiColorPicker.js +326 -0
- package/vue/chunks/UiCombobox.js +1 -1
- package/vue/chunks/UiContainer.js +1 -1
- package/vue/chunks/UiContextMenu.js +1 -1
- package/vue/chunks/UiCover.js +1 -1
- package/vue/chunks/UiDescriptionItem.js +1 -1
- package/vue/chunks/UiDescriptionList.js +1 -1
- package/vue/chunks/UiDialog.js +1 -1
- package/vue/chunks/UiDisclosure.js +1 -1
- package/vue/chunks/UiEditable.js +1 -1
- package/vue/chunks/UiEditorImageToolbar.js +1 -1
- package/vue/chunks/UiEditorInsertTableGrid.js +1 -1
- package/vue/chunks/UiEditorLinkForm.js +1 -1
- package/vue/chunks/UiEditorMentionMenu.js +1 -1
- package/vue/chunks/UiEditorMentionMenuItem.js +1 -1
- package/vue/chunks/UiEditorSlashMenu.js +1 -1
- package/vue/chunks/UiEditorSlashMenuGroup.js +1 -1
- package/vue/chunks/UiEditorSlashMenuItem.js +1 -1
- package/vue/chunks/UiEditorSurface.js +1 -1
- package/vue/chunks/UiEditorTableContextMenu.js +1 -1
- package/vue/chunks/UiEditorTableOverlay.js +1 -1
- package/vue/chunks/UiEditorTableToolbar.js +1 -1
- package/vue/chunks/UiEditorToolbar.js +1 -1
- package/vue/chunks/UiFloatingActionButton.js +1 -1
- package/vue/chunks/UiFormField.js +2 -2
- package/vue/chunks/UiGrid.js +1 -1
- package/vue/chunks/UiIcon.js +5 -1
- package/vue/chunks/UiIconButton.js +2 -2
- package/vue/chunks/UiImage.js +1 -1
- package/vue/chunks/UiInput.js +1 -1
- package/vue/chunks/UiInputGroup.js +1 -1
- package/vue/chunks/UiList.js +1 -1
- package/vue/chunks/UiListItem.js +1 -1
- package/vue/chunks/UiListbox.js +1 -1
- package/vue/chunks/UiMenu.js +1 -1
- package/vue/chunks/UiMenuGroup.js +1 -1
- package/vue/chunks/UiMenuItem.js +1 -1
- package/vue/chunks/UiMeter.js +1 -1
- package/vue/chunks/UiNavItem.js +1 -1
- package/vue/chunks/UiPageHeader.js +1 -1
- package/vue/chunks/UiPopover.js +1 -1
- package/vue/chunks/UiRadio.js +1 -1
- package/vue/chunks/UiRadioGroup.js +1 -1
- package/vue/chunks/UiReel.js +1 -1
- package/vue/chunks/UiScrollArea.js +1 -1
- package/vue/chunks/UiSearchResultRow.js +1 -1
- package/vue/chunks/UiSearchShell.js +1 -1
- package/vue/chunks/UiSection.js +1 -1
- package/vue/chunks/UiSelect.js +1 -1
- package/vue/chunks/UiSeparator.js +1 -1
- package/vue/chunks/UiSidebar.js +1 -1
- package/vue/chunks/UiSpinner.js +1 -1
- package/vue/chunks/UiStack.js +1 -1
- package/vue/chunks/UiStatusMessage.js +1 -1
- package/vue/chunks/UiSwatch.js +1 -1
- package/vue/chunks/UiSwitch.js +1 -1
- package/vue/chunks/UiSwitcher.js +1 -1
- package/vue/chunks/UiTable.js +1 -1
- package/vue/chunks/UiTabs.js +3 -3
- package/vue/chunks/UiText.js +1 -1
- package/vue/chunks/UiTextarea.js +1 -1
- package/vue/chunks/UiToast.js +1 -1
- package/vue/chunks/UiToastRegion.js +1 -1
- package/vue/chunks/UiTooltip.js +1 -1
- package/vue/chunks/UiTopBar.js +1 -1
- package/vue/chunks/UiTree.js +1 -1
- package/vue/chunks/UiTreeItem.js +1 -1
- package/vue/components.css +1857 -1654
- package/vue/editor/index.js +28 -11
- package/vue/index.d.ts +1 -0
- package/vue/index.js +3 -2
package/docs/theme.mjs
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/** The shared authoring schema; ids remain stable in saved recipes. */
|
|
2
|
+
export const themeFields = [
|
|
3
|
+
['Colour', 'action', 'Action', '--ui-accent', 'colour', '#5b55d6', 'Primary commands and selected controls.'],
|
|
4
|
+
['Colour', 'canvas', 'Canvas', '--ui-surface', 'colour', '#f6f6f8', 'The ground behind surfaces.'],
|
|
5
|
+
['Colour', 'surface', 'Surface', '--ui-surface-raised', 'colour', '#ffffff', 'Fields, cards and floating surfaces.'],
|
|
6
|
+
['Colour', 'text', 'Text', '--ui-text', 'colour', '#1a1a1a', 'Readable content; supporting text follows this and Surface.'],
|
|
7
|
+
['Type', 'body-font', 'Body font', '--ui-font-sans', 'font', 'system-ui, sans-serif', 'The shared interface typeface.'],
|
|
8
|
+
['Type', 'display-font', 'Display font', '--ui-font-display', 'font', 'system-ui, sans-serif', 'The heading typeface.'],
|
|
9
|
+
['Type', 'text-size', 'Text size', '--ui-font-size', 'positive-length', '16px', 'Base type and choice-mark size. Accepts native CSS lengths, such as 1rem.'],
|
|
10
|
+
['Type', 'text-weight', 'Emphasis weight', '--ui-font-medium', 'weight', '500', 'Control-label emphasis; body and headings keep their roles.'],
|
|
11
|
+
['Size & spacing', 'control-size', 'Control size', '--ui-control-size', 'positive-length', '40px', 'One shared height for buttons, fields and swatches.'],
|
|
12
|
+
['Size & spacing', 'density', 'Density', '--ui-density', 'positive', '1', 'More or less breathing room throughout the interface.'],
|
|
13
|
+
['Size & spacing', 'scale-contrast', 'Size ratio', '--ui-scale-ratio', 'ratio', '1.2', 'The multiplier between small, medium and large controls.'],
|
|
14
|
+
['Size & spacing', 'space-curve', 'Spacing curve', '--ui-space-curve', 'nonnegative', '1', 'Spacing growth: 1 is linear, 2 is quadratic. Independent of control sizes.'],
|
|
15
|
+
['Size & spacing', 'corner-roundness', 'Corner roundness', '--ui-radius-md', 'length', '8px', 'One corner family across controls and surfaces.'],
|
|
16
|
+
['Size & spacing', 'line-weight', 'Line weight', '--ui-border-width', 'length', '1px', 'Shared edge weight; focus stays independently visible.'],
|
|
17
|
+
['Material', 'outer-depth', 'Outer depth', '--ui-outer-depth', 'nonnegative', '0.6', 'How strongly controls and floating surfaces rise above the page.'],
|
|
18
|
+
['Material', 'inner-depth', 'Inner depth', '--ui-inner-depth', 'nonnegative', '0.3', 'How strongly fields and pressed controls sit into their surface.'],
|
|
19
|
+
['Material', 'translucency', 'Overlay translucency', '--ui-overlay-translucency', 'fraction', '0', 'How much background comes through floating surfaces.'],
|
|
20
|
+
['Material', 'edge-light', 'Edge light', '--ui-edge-light', 'fraction', '0', 'Light caught by surface edges, independent of depth.'],
|
|
21
|
+
['Motion', 'response-time', 'Response time', '--ui-motion-fast', 'time', '120ms', 'Shared feedback pace; floating transitions take proportionally longer.'],
|
|
22
|
+
['Motion', 'response-curve', 'Response curve', '--ui-motion-ease', 'easing', 'cubic-bezier(0.2,0,0.2,1)', 'How movement accelerates and settles.'],
|
|
23
|
+
].map(([family, id, label, property, type, defaultValue, description]) => Object.freeze({ family, id, label, property, type, defaultValue, description }));
|
|
24
|
+
|
|
25
|
+
export const defaultRecipe = () => ({ schemaVersion: 1, values: Object.fromEntries(themeFields.map(field => [field.id, field.defaultValue])) });
|
|
26
|
+
const starting = values => ({ schemaVersion: 1, values: { ...defaultRecipe().values, ...values } });
|
|
27
|
+
export const startingPoints = {
|
|
28
|
+
clear: defaultRecipe(),
|
|
29
|
+
library: starting({ action: '#2e1228', canvas: '#f7f7f5', surface: '#fffefd', text: '#0d0c0c', 'body-font': 'Arial, sans-serif', 'display-font': 'Georgia, serif', 'text-weight': '400', 'control-size': '42px', 'scale-contrast': '1.18', 'outer-depth': '1', 'inner-depth': '1', translucency: '0.18', 'edge-light': '1', 'response-time': '150ms', 'response-curve': 'ease' }),
|
|
30
|
+
editorial: starting({ action: '#182c24', canvas: '#eee9dc', surface: '#fffdf5', text: '#182c24', 'corner-roundness': '0px', 'outer-depth': '0', 'inner-depth': '0', 'body-font': 'Georgia, serif', 'display-font': 'Georgia, serif', 'text-weight': '400', 'line-weight': '2px', 'response-time': '90ms', 'response-curve': 'linear' }),
|
|
31
|
+
night: starting({ action: '#a7b8ff', canvas: '#11141c', surface: '#202634', text: '#edf1fb', 'corner-roundness': '12px', 'outer-depth': '1.4', 'inner-depth': '0.45', translucency: '0.2', 'edge-light': '0.65', 'response-time': '210ms', 'response-curve': 'cubic-bezier(0.2,0.8,0.2,1)' }),
|
|
32
|
+
garden: starting({ action: '#256342', canvas: '#eef5e7', surface: '#fcfff6', text: '#173121', 'corner-roundness': '22px', 'outer-depth': '0.35', 'inner-depth': '0', 'edge-light': '0.2', 'control-size': '46px', 'scale-contrast': '1.24', density: '1.05', 'response-time': '180ms', 'response-curve': 'cubic-bezier(0.16,1,0.3,1)' }),
|
|
33
|
+
};
|
|
34
|
+
export const startingPointLabels = { clear: 'Clear', library: 'Library', editorial: 'Editorial', night: 'Night', garden: 'Garden' };
|
|
35
|
+
const scalar = /^[+]?(?:\d+(?:\.\d*)?|\.\d+)$/;
|
|
36
|
+
const length = /^(?:0|[+]?(?:\d+(?:\.\d*)?|\.\d+)(?:px|rem|em|ex|ch|cap|ic|lh|rlh|vw|vh|vi|vb|vmin|vmax|svw|svh|lvw|lvh|dvw|dvh|cm|mm|Q|in|pt|pc))$/;
|
|
37
|
+
const font = /^(?:"[^"\\;{}<>@\x00-\x1f]+"|'[^'\\;{}<>@\x00-\x1f]+'|[\p{L}_-][\p{L}\p{N}_ -]*)(?:\s*,\s*(?:"[^"\\;{}<>@\x00-\x1f]+"|'[^'\\;{}<>@\x00-\x1f]+'|[\p{L}_-][\p{L}\p{N}_ -]*))*$/u;
|
|
38
|
+
const time = /^[+]?(?:\d+(?:\.\d*)?|\.\d+)(?:ms|s)$/;
|
|
39
|
+
function easing(value) {
|
|
40
|
+
if (/^(ease|linear|ease-in|ease-out|ease-in-out|step-start|step-end)$/.test(value)) return true;
|
|
41
|
+
const match = /^cubic-bezier\(\s*([\d.+-]+)\s*,\s*([\d.+-]+)\s*,\s*([\d.+-]+)\s*,\s*([\d.+-]+)\s*\)$/.exec(value);
|
|
42
|
+
return Boolean(match && match.slice(1).every(n => Number.isFinite(Number(n))) && [1, 3].every(i => Number(match[i]) >= 0 && Number(match[i]) <= 1));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Validate the whole recipe before previewing or writing any output. */
|
|
46
|
+
export function validateRecipe(input) {
|
|
47
|
+
if (!input || input.schemaVersion !== 1 || !input.values || typeof input.values !== 'object' || Array.isArray(input.values)) throw new Error('Unsupported theme recipe version or values.');
|
|
48
|
+
const known = new Set(themeFields.map(field => field.id));
|
|
49
|
+
for (const key of Object.keys(input.values)) if (!known.has(key)) throw new Error(`Unknown theme decision ${key}.`);
|
|
50
|
+
const values = { ...defaultRecipe().values, ...input.values };
|
|
51
|
+
for (const field of themeFields) {
|
|
52
|
+
const value = values[field.id];
|
|
53
|
+
let valid = typeof value === 'string' && value.length > 0;
|
|
54
|
+
if (valid) switch (field.type) {
|
|
55
|
+
case 'colour': valid = /^#[\da-f]{6}$/i.test(value); break;
|
|
56
|
+
case 'font': valid = font.test(value); break;
|
|
57
|
+
case 'length': valid = length.test(value) && Number.isFinite(parseFloat(value)); break;
|
|
58
|
+
case 'positive-length': valid = length.test(value) && Number.isFinite(parseFloat(value)) && parseFloat(value) > 0; break;
|
|
59
|
+
case 'time': valid = time.test(value) && Number.isFinite(parseFloat(value)); break;
|
|
60
|
+
case 'easing': valid = easing(value); break;
|
|
61
|
+
default: {
|
|
62
|
+
const number = Number(value); valid = scalar.test(value) && Number.isFinite(number);
|
|
63
|
+
if (field.type === 'positive') valid &&= number > 0;
|
|
64
|
+
if (field.type === 'ratio') valid &&= number >= 1;
|
|
65
|
+
if (field.type === 'fraction') valid &&= number >= 0 && number <= 1;
|
|
66
|
+
if (field.type === 'weight') valid &&= number >= 1 && number <= 1000;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!valid) throw new Error(`${field.label}: enter a valid ${field.type.replaceAll('-', ' ')} value.`);
|
|
70
|
+
}
|
|
71
|
+
return { schemaVersion: 1, values };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Match presets by their complete semantic recipe, including locally saved themes. */
|
|
75
|
+
export function startingPointFor(input) {
|
|
76
|
+
const recipe = JSON.stringify(validateRecipe(input));
|
|
77
|
+
return Object.entries(startingPoints).find(([, value]) => JSON.stringify(value) === recipe)?.[0] ?? 'custom';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const rgb = hex => [1, 3, 5].map(i => parseInt(hex.slice(i, i + 2), 16));
|
|
81
|
+
const mix = (a, b, weight) => '#' + rgb(a).map((n, i) => Math.round(n * weight + rgb(b)[i] * (1 - weight)).toString(16).padStart(2, '0')).join('');
|
|
82
|
+
const luminance = hex => rgb(hex).map(n => { const s = n / 255; return s <= .04045 ? s / 12.92 : ((s + .055) / 1.055) ** 2.4; }).reduce((sum, n, i) => sum + n * [.2126, .7152, .0722][i], 0);
|
|
83
|
+
const contrast = (a, b) => (Math.max(luminance(a), luminance(b)) + .05) / (Math.min(luminance(a), luminance(b)) + .05);
|
|
84
|
+
const foreground = (fill, light, dark) => [light, dark, '#ffffff', '#000000'].sort((a, b) => contrast(fill, b) - contrast(fill, a))[0];
|
|
85
|
+
|
|
86
|
+
/** Shared public seeds; combine with theme-system.css for a standalone exported theme. */
|
|
87
|
+
export function themeCSS(input, systemCSS = '') {
|
|
88
|
+
const { values } = validateRecipe(input);
|
|
89
|
+
const tokens = Object.fromEntries(themeFields.map(field => [field.property, values[field.id]]));
|
|
90
|
+
tokens['--ui-on-accent'] = foreground(values.action, values.surface, values.text);
|
|
91
|
+
tokens['--ui-surface-sunken'] = mix(values.surface, values.canvas, .92);
|
|
92
|
+
let muted = values.text;
|
|
93
|
+
for (let weight = .72; weight <= 1; weight += .01) { muted = mix(values.text, values.surface, weight); if (contrast(muted, values.surface) >= 4.5) break; }
|
|
94
|
+
tokens['--ui-text-secondary'] = muted;
|
|
95
|
+
let danger = '#c92d1e';
|
|
96
|
+
for (let weight = 0; weight <= 1; weight += .02) { danger = mix('#c92d1e', values.text, 1 - weight); if (Math.min(contrast(danger, values.surface), contrast(danger, values.canvas)) >= 4.5) break; }
|
|
97
|
+
tokens['--ui-danger'] = danger; tokens['--ui-on-danger'] = foreground(danger, values.surface, values.text);
|
|
98
|
+
tokens['--ui-focus-width'] = 'max(2px, calc(var(--ui-border-width) * 2))';
|
|
99
|
+
return `/* Looma shared semantic theme. */\n${systemCSS}\n:root, [data-theme], [data-contrast] {\n${Object.entries(tokens).map(([name, value]) => ` ${name}: ${value};`).join('\n')}\n}\n@media (prefers-reduced-motion: reduce) {\n :root, [data-theme], [data-contrast] { --ui-motion-fast: 0ms; --ui-motion-base: 0ms; --ui-motion-press: 0ms; --ui-press-scale: 1; }\n}\n`;
|
|
100
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { lstat, mkdir, open, realpath, unlink } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
export async function rejectSymlink(file) {
|
|
5
|
+
try { if ((await lstat(file)).isSymbolicLink()) throw new Error(`Looma's generated path cannot be a symlink: ${file}.`); }
|
|
6
|
+
catch (error) { if (error.code !== 'ENOENT') throw error; }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Generated sources and tooling wrappers stay in owned cache directories. */
|
|
10
|
+
export async function cacheDirectory(root, name = '') {
|
|
11
|
+
root = await realpath(path.resolve(root));
|
|
12
|
+
if (name && !/^[a-z][a-z-]*$/.test(name)) throw new Error('Invalid Looma cache directory.');
|
|
13
|
+
const cache = path.join(root, '.looma');
|
|
14
|
+
await rejectSymlink(cache); await mkdir(cache, { recursive: true });
|
|
15
|
+
const directory = path.join(cache, name);
|
|
16
|
+
await rejectSymlink(directory); await mkdir(directory, { recursive: true });
|
|
17
|
+
return directory;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** One complete preparation/build owns the generated tree, including across CLI processes. */
|
|
21
|
+
export async function withBuildLock(root, action) {
|
|
22
|
+
const lockFile = path.join(await cacheDirectory(root), 'docs-build.lock');
|
|
23
|
+
await rejectSymlink(lockFile);
|
|
24
|
+
let lock;
|
|
25
|
+
try { lock = await open(lockFile, 'wx', 0o600); }
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (error.code === 'EEXIST') throw new Error('Another documentation build holds .looma/docs-build.lock. Retry after it finishes. If the old process stopped, close it before removing that lock.');
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
try { await lock.writeFile(JSON.stringify({ pid: process.pid })); return await action(); }
|
|
31
|
+
finally { try { await lock.close(); } finally { await unlink(lockFile); } }
|
|
32
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@threadlabs/looma",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -82,6 +82,14 @@
|
|
|
82
82
|
"types": "./editor/expressmark.d.ts",
|
|
83
83
|
"import": "./editor/expressmark.js",
|
|
84
84
|
"default": "./editor/expressmark.js"
|
|
85
|
+
},
|
|
86
|
+
"./theme-system.css": "./theme-system.css",
|
|
87
|
+
"./docs/catalog.json": "./docs/catalog.json",
|
|
88
|
+
"./docs/*": "./docs/*",
|
|
89
|
+
"./docs": {
|
|
90
|
+
"types": "./docs/index.d.ts",
|
|
91
|
+
"import": "./docs/index.mjs",
|
|
92
|
+
"default": "./docs/index.mjs"
|
|
85
93
|
}
|
|
86
94
|
},
|
|
87
95
|
"files": [
|
|
@@ -95,7 +103,9 @@
|
|
|
95
103
|
"*.css",
|
|
96
104
|
"README.md",
|
|
97
105
|
"LICENSE",
|
|
98
|
-
"EXPRESSIVE-MARKDOWN.md"
|
|
106
|
+
"EXPRESSIVE-MARKDOWN.md",
|
|
107
|
+
"docs/",
|
|
108
|
+
"bin/"
|
|
99
109
|
],
|
|
100
110
|
"sideEffects": [
|
|
101
111
|
"./dist/index.js",
|
|
@@ -116,7 +126,10 @@
|
|
|
116
126
|
"@tiptap/core": ">=2 <3",
|
|
117
127
|
"@tiptap/pm": ">=2 <3",
|
|
118
128
|
"@tiptap/vue-3": ">=2 <3",
|
|
119
|
-
"vue": "^3.5.43"
|
|
129
|
+
"vue": "^3.5.43",
|
|
130
|
+
"markupress": "^0.8.0",
|
|
131
|
+
"@nextwebwg/htmlkit": "1.0.0-alpha.69",
|
|
132
|
+
"vite": "^8.3.4"
|
|
120
133
|
},
|
|
121
134
|
"peerDependenciesMeta": {
|
|
122
135
|
"@tiptap/core": {
|
|
@@ -130,6 +143,15 @@
|
|
|
130
143
|
},
|
|
131
144
|
"vue": {
|
|
132
145
|
"optional": true
|
|
146
|
+
},
|
|
147
|
+
"markupress": {
|
|
148
|
+
"optional": true
|
|
149
|
+
},
|
|
150
|
+
"@nextwebwg/htmlkit": {
|
|
151
|
+
"optional": true
|
|
152
|
+
},
|
|
153
|
+
"vite": {
|
|
154
|
+
"optional": true
|
|
133
155
|
}
|
|
134
156
|
},
|
|
135
157
|
"devDependencies": {
|
|
@@ -184,6 +206,9 @@
|
|
|
184
206
|
"engines": {
|
|
185
207
|
"node": ">=22.22.2 <23 || >=24.15 <25"
|
|
186
208
|
},
|
|
209
|
+
"bin": {
|
|
210
|
+
"looma-docs": "./bin/looma-docs.mjs"
|
|
211
|
+
},
|
|
187
212
|
"scripts": {
|
|
188
213
|
"build": "node build.mjs",
|
|
189
214
|
"lint": "vue-tsc -p tsconfig.json --noEmit",
|
package/styles/ui-action-bar.css
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
--_ui-action-bar-gap: var(--ui-action-bar-gap);
|
|
22
22
|
|
|
23
23
|
--_gap: var(--ui-space-2);
|
|
24
|
-
display: block;
|
|
24
|
+
display: block !important;
|
|
25
25
|
/* A size container sizes itself from its container, never its content. */
|
|
26
26
|
container-type: inline-size;
|
|
27
27
|
inline-size: 100%;
|
|
@@ -32,16 +32,16 @@
|
|
|
32
32
|
.tertiary,
|
|
33
33
|
.secondary,
|
|
34
34
|
.primary {
|
|
35
|
-
display: flex;
|
|
36
|
-
flex-wrap: wrap;
|
|
37
|
-
align-items: center;
|
|
38
|
-
gap: var(--_ui-action-bar-gap, var(--_gap));
|
|
35
|
+
display: flex !important;
|
|
36
|
+
flex-wrap: wrap !important;
|
|
37
|
+
align-items: center !important;
|
|
38
|
+
gap: var(--_ui-action-bar-gap, var(--_gap)) !important;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/* The tertiary group takes the spare space, pushing the rest to the end edge; without it, the
|
|
42
42
|
rest still ends the row. */
|
|
43
43
|
.bar {
|
|
44
|
-
justify-content: flex-end;
|
|
44
|
+
justify-content: flex-end !important;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
.tertiary {
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
.tertiary:empty,
|
|
52
52
|
.secondary:empty,
|
|
53
53
|
.primary:empty {
|
|
54
|
-
display: none;
|
|
54
|
+
display: none !important;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/* A narrow container stacks the actions full width, primary on top: the row turned on its end,
|
|
@@ -61,9 +61,9 @@
|
|
|
61
61
|
.tertiary,
|
|
62
62
|
.secondary,
|
|
63
63
|
.primary {
|
|
64
|
-
flex-direction: column-reverse;
|
|
65
|
-
flex-wrap: nowrap;
|
|
66
|
-
align-items: stretch;
|
|
64
|
+
flex-direction: column-reverse !important;
|
|
65
|
+
flex-wrap: nowrap !important;
|
|
66
|
+
align-items: stretch !important;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
.tertiary {
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
|
|
74
74
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
75
75
|
:scope:where([data-component~="ui-action-bar"])[hidden] {
|
|
76
|
-
display: none;
|
|
76
|
+
display: none !important;
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
@scope ([data-component~="ui-action-bar"]) to ([data-component]) {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
}
|
|
9
9
|
@scope ([data-component~="ui-affordance-scope"]) to ([data-component], [data-slotted]) {
|
|
10
10
|
:scope:where([data-component~="ui-affordance-scope"]) {
|
|
11
|
-
display: contents;
|
|
11
|
+
display: contents !important;
|
|
12
12
|
--ui-affordance-scope-engaged: 0;
|
|
13
13
|
--ui-affordance-scope-guide: 1;
|
|
14
14
|
}
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
26
26
|
:scope:where([data-component~="ui-affordance-scope"])[hidden] {
|
|
27
|
-
display: none;
|
|
27
|
+
display: none !important;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
@scope ([data-component~="ui-affordance-scope"]) to ([data-component]) {
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
* a white gap out of the avatar underneath. */
|
|
27
27
|
--_overlap-shadow: -1px 0 0 0 rgb(0 0 0 / 0.22);
|
|
28
28
|
|
|
29
|
-
display: flex;
|
|
30
|
-
align-items: center;
|
|
31
|
-
flex-direction: row;
|
|
32
|
-
gap: 0;
|
|
29
|
+
display: flex !important;
|
|
30
|
+
align-items: center !important;
|
|
31
|
+
flex-direction: row !important;
|
|
32
|
+
gap: 0 !important;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/* Overlap and the separating shadow are applied by the controller: slotted avatars are nested
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
.overflow {
|
|
43
|
-
margin-inline-start: -0.5rem;
|
|
44
|
-
display: inline-flex;
|
|
45
|
-
align-items: center;
|
|
46
|
-
justify-content: center;
|
|
43
|
+
margin-inline-start: -0.5rem !important;
|
|
44
|
+
display: inline-flex !important;
|
|
45
|
+
align-items: center !important;
|
|
46
|
+
justify-content: center !important;
|
|
47
47
|
inline-size: 2.5rem;
|
|
48
48
|
block-size: 2.5rem;
|
|
49
49
|
border-radius: var(--ui-radius-round);
|
|
@@ -60,13 +60,13 @@
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
:scope:where([data-component~="ui-avatar-group"])[data-ui-avatar-group-state~="size=sm"] .overflow {
|
|
63
|
-
margin-inline-start: -0.25rem;
|
|
63
|
+
margin-inline-start: -0.25rem !important;
|
|
64
64
|
inline-size: 1.75rem;
|
|
65
65
|
block-size: 1.75rem;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
:scope:where([data-component~="ui-avatar-group"])[data-ui-avatar-group-state~="size=xs"] .overflow {
|
|
69
|
-
margin-inline-start: -0.1875rem;
|
|
69
|
+
margin-inline-start: -0.1875rem !important;
|
|
70
70
|
inline-size: 1.25rem;
|
|
71
71
|
block-size: 1.25rem;
|
|
72
72
|
/* Matches the xs Avatar's initials. */
|
|
@@ -75,12 +75,12 @@
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
.overflow[hidden] {
|
|
78
|
-
display: none;
|
|
78
|
+
display: none !important;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
82
82
|
:scope:where([data-component~="ui-avatar-group"])[hidden] {
|
|
83
|
-
display: none;
|
|
83
|
+
display: none !important;
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
@scope ([data-component~="ui-avatar-group"]) to ([data-component]) {
|
|
@@ -89,12 +89,12 @@
|
|
|
89
89
|
/* Overlap and the separating shadow are applied by the controller: slotted avatars are nested
|
|
90
90
|
* component roots outside this style scope. */
|
|
91
91
|
:where([data-slotted], [data-slotted] *):is(*) {
|
|
92
|
-
margin-inline-start: -0.5rem;
|
|
92
|
+
margin-inline-start: -0.5rem !important;
|
|
93
93
|
flex-shrink: 0;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
:where([data-slotted], [data-slotted] *):is(*:first-child) {
|
|
97
|
-
margin-inline-start: 0;
|
|
97
|
+
margin-inline-start: 0 !important;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
package/styles/ui-avatar.css
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
:scope:where([data-component~="ui-avatar"]) {
|
|
33
33
|
--_ui-default-icon-size: 1.25rem;
|
|
34
|
-
display: inline-grid;
|
|
34
|
+
display: inline-grid !important;
|
|
35
35
|
place-items: center;
|
|
36
36
|
overflow: hidden;
|
|
37
37
|
inline-size: 2.5rem;
|
|
@@ -85,9 +85,9 @@
|
|
|
85
85
|
|
|
86
86
|
.fallback {
|
|
87
87
|
grid-area: 1 / 1;
|
|
88
|
-
display: inline-flex;
|
|
89
|
-
align-items: center;
|
|
90
|
-
justify-content: center;
|
|
88
|
+
display: inline-flex !important;
|
|
89
|
+
align-items: center !important;
|
|
90
|
+
justify-content: center !important;
|
|
91
91
|
inline-size: 100%;
|
|
92
92
|
block-size: 100%;
|
|
93
93
|
}
|
|
@@ -97,21 +97,21 @@
|
|
|
97
97
|
* Trimming applies to block containers, so the box is a block with centred content. */
|
|
98
98
|
@supports (text-box-trim: trim-both) {
|
|
99
99
|
.fallback {
|
|
100
|
-
display: block;
|
|
100
|
+
display: block !important;
|
|
101
101
|
text-align: center;
|
|
102
|
-
align-content: center;
|
|
102
|
+
align-content: center !important;
|
|
103
103
|
text-box-trim: trim-both;
|
|
104
104
|
text-box-edge: cap alphabetic;
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
[hidden] {
|
|
109
|
-
display: none;
|
|
109
|
+
display: none !important;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
113
113
|
:scope:where([data-component~="ui-avatar"])[hidden] {
|
|
114
|
-
display: none;
|
|
114
|
+
display: none !important;
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
@scope ([data-component~="ui-avatar"]) to ([data-component]) {
|
package/styles/ui-badge.css
CHANGED
|
@@ -85,14 +85,14 @@
|
|
|
85
85
|
--_badge-color-text: var(--_badge-color-ink);
|
|
86
86
|
--_badge-outline-surface: var(--ui-badge-surface, var(--_badge-color-surface, var(--_badge-surface)));
|
|
87
87
|
|
|
88
|
-
display: inline-flex;
|
|
89
|
-
align-items: center;
|
|
90
|
-
justify-content: center;
|
|
91
|
-
gap: var(--ui-space-1);
|
|
92
|
-
box-sizing: border-box;
|
|
88
|
+
display: inline-flex !important;
|
|
89
|
+
align-items: center !important;
|
|
90
|
+
justify-content: center !important;
|
|
91
|
+
gap: var(--ui-space-1) !important;
|
|
92
|
+
box-sizing: border-box !important;
|
|
93
93
|
min-inline-size: 0;
|
|
94
94
|
max-inline-size: 100%;
|
|
95
|
-
padding: var(--ui-badge-padding-block, var(--ui-space-0-5)) var(--ui-badge-padding-inline, var(--ui-space-2));
|
|
95
|
+
padding: var(--ui-badge-padding-block, var(--ui-space-0-5)) var(--ui-badge-padding-inline, var(--ui-space-2)) !important;
|
|
96
96
|
border: var(--ui-border-width) solid var(--ui-badge-border, var(--_badge-color-border, var(--_badge-border)));
|
|
97
97
|
border-radius: var(--ui-radius-round);
|
|
98
98
|
background: var(--_badge-outline-surface);
|
|
@@ -107,26 +107,26 @@
|
|
|
107
107
|
/* A constrained badge keeps its surface intact and ellipsizes only its label. The full
|
|
108
108
|
text stays in the DOM for accessible names and consumers' selected values. */
|
|
109
109
|
.label {
|
|
110
|
-
display: block;
|
|
110
|
+
display: block !important;
|
|
111
111
|
min-inline-size: 0;
|
|
112
112
|
overflow: hidden;
|
|
113
113
|
text-overflow: ellipsis;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
.label:empty {
|
|
117
|
-
display: none;
|
|
117
|
+
display: none !important;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
/* Icon content has its own flex item so label ellipsis never clips its strokes. */
|
|
121
121
|
.icon {
|
|
122
|
-
display: inline-flex;
|
|
123
|
-
align-items: center;
|
|
124
|
-
justify-content: center;
|
|
122
|
+
display: inline-flex !important;
|
|
123
|
+
align-items: center !important;
|
|
124
|
+
justify-content: center !important;
|
|
125
125
|
flex: none;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
.icon:empty {
|
|
129
|
-
display: none;
|
|
129
|
+
display: none !important;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
/* Ordinary icon-plus-text children keep inline ellipsis, with explicit glyph spacing. */
|
|
@@ -139,15 +139,15 @@
|
|
|
139
139
|
Vertical ink remains visible so trimming never cuts off ascenders or descenders. */
|
|
140
140
|
@supports (text-box-trim: trim-both) {
|
|
141
141
|
:scope:where([data-component~="ui-badge"]) {
|
|
142
|
-
display: inline-block;
|
|
142
|
+
display: inline-block !important;
|
|
143
143
|
min-block-size: var(--ui-badge-min-block-size, 1.5rem);
|
|
144
144
|
text-align: center;
|
|
145
|
-
align-content: center;
|
|
145
|
+
align-content: center !important;
|
|
146
146
|
text-box-trim: none;
|
|
147
147
|
}
|
|
148
148
|
:scope:where([data-component~="ui-badge"]):has(.icon:not(:empty)),
|
|
149
149
|
:scope:where([data-component~="ui-badge"]):has(.label svg) {
|
|
150
|
-
display: inline-flex;
|
|
150
|
+
display: inline-flex !important;
|
|
151
151
|
text-box-trim: none;
|
|
152
152
|
}
|
|
153
153
|
.label:not(:has(svg)) {
|
|
@@ -159,12 +159,12 @@
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="size=xs"] {
|
|
162
|
-
box-sizing: border-box;
|
|
162
|
+
box-sizing: border-box !important;
|
|
163
163
|
min-inline-size: 1rem;
|
|
164
164
|
min-block-size: var(--ui-badge-min-block-size, 1rem);
|
|
165
165
|
/* Compact text still needs room at both rounded edges. Fixed marks override this
|
|
166
166
|
padding below; ordinary text badges retain their larger spacing. */
|
|
167
|
-
padding: var(--ui-badge-padding-block, 0) var(--ui-badge-padding-inline, var(--ui-space-1));
|
|
167
|
+
padding: var(--ui-badge-padding-block, 0) var(--ui-badge-padding-inline, var(--ui-space-1)) !important;
|
|
168
168
|
font-size: var(--ui-badge-font-size, var(--ui-font-size-2xs));
|
|
169
169
|
line-height: var(--ui-badge-line-height, 1);
|
|
170
170
|
}
|
|
@@ -338,14 +338,14 @@
|
|
|
338
338
|
/* An icon mark keeps the existing tone recipe and follows the global spacing and radius. */
|
|
339
339
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=square"] {
|
|
340
340
|
--_badge-square-size: var(--ui-badge-square-size, calc(var(--ui-space-4) * 2));
|
|
341
|
-
display: inline-flex;
|
|
342
|
-
box-sizing: border-box;
|
|
341
|
+
display: inline-flex !important;
|
|
342
|
+
box-sizing: border-box !important;
|
|
343
343
|
flex: none;
|
|
344
344
|
inline-size: var(--_badge-square-size);
|
|
345
345
|
block-size: var(--_badge-square-size);
|
|
346
346
|
min-inline-size: var(--_badge-square-size);
|
|
347
347
|
min-block-size: var(--_badge-square-size);
|
|
348
|
-
padding: 0;
|
|
348
|
+
padding: 0 !important;
|
|
349
349
|
border-radius: var(--ui-radius-md);
|
|
350
350
|
text-box-trim: none;
|
|
351
351
|
}
|
|
@@ -359,25 +359,25 @@
|
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=square"] .label {
|
|
362
|
-
display: inline-flex;
|
|
363
|
-
align-items: center;
|
|
364
|
-
justify-content: center;
|
|
362
|
+
display: inline-flex !important;
|
|
363
|
+
align-items: center !important;
|
|
364
|
+
justify-content: center !important;
|
|
365
365
|
}
|
|
366
366
|
|
|
367
367
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=square"] .label:empty {
|
|
368
|
-
display: none;
|
|
368
|
+
display: none !important;
|
|
369
369
|
}
|
|
370
370
|
|
|
371
371
|
/* A visible glyph needs fixed geometry, unlike a content-sized pill or a hidden-label dot. */
|
|
372
372
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=circle"] {
|
|
373
373
|
--_badge-circle-size: var(--ui-badge-circle-size, calc(var(--ui-space-3) * 2));
|
|
374
|
-
display: inline-flex;
|
|
374
|
+
display: inline-flex !important;
|
|
375
375
|
flex: none;
|
|
376
376
|
inline-size: var(--_badge-circle-size);
|
|
377
377
|
block-size: var(--_badge-circle-size);
|
|
378
378
|
min-inline-size: var(--_badge-circle-size);
|
|
379
379
|
min-block-size: var(--_badge-circle-size);
|
|
380
|
-
padding: 0;
|
|
380
|
+
padding: 0 !important;
|
|
381
381
|
border-radius: var(--ui-radius-round);
|
|
382
382
|
text-box-trim: none;
|
|
383
383
|
}
|
|
@@ -395,15 +395,15 @@
|
|
|
395
395
|
}
|
|
396
396
|
|
|
397
397
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=circle"] .label {
|
|
398
|
-
display: inline-flex;
|
|
399
|
-
align-items: center;
|
|
400
|
-
justify-content: center;
|
|
398
|
+
display: inline-flex !important;
|
|
399
|
+
align-items: center !important;
|
|
400
|
+
justify-content: center !important;
|
|
401
401
|
line-height: 1;
|
|
402
402
|
text-box-trim: none;
|
|
403
403
|
}
|
|
404
404
|
|
|
405
405
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=circle"] .label:empty {
|
|
406
|
-
display: none;
|
|
406
|
+
display: none !important;
|
|
407
407
|
}
|
|
408
408
|
|
|
409
409
|
/* Center capital and numeral ink, rather than the font's ascent/descent line box.
|
|
@@ -411,7 +411,7 @@
|
|
|
411
411
|
@supports (text-box-trim: trim-both) {
|
|
412
412
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=circle"] .label:not(:has(svg)),
|
|
413
413
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=square"] .label:not(:has(svg)) {
|
|
414
|
-
display: block;
|
|
414
|
+
display: block !important;
|
|
415
415
|
text-box-trim: trim-both;
|
|
416
416
|
text-box-edge: cap alphabetic;
|
|
417
417
|
overflow: visible;
|
|
@@ -421,13 +421,13 @@
|
|
|
421
421
|
/* A dot uses the badge's tone recipe; only its silhouette and visible label change. */
|
|
422
422
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=dot"] {
|
|
423
423
|
position: relative;
|
|
424
|
-
box-sizing: border-box;
|
|
424
|
+
box-sizing: border-box !important;
|
|
425
425
|
flex: none;
|
|
426
426
|
inline-size: var(--ui-badge-dot-size, var(--ui-space-2));
|
|
427
427
|
block-size: var(--ui-badge-dot-size, var(--ui-space-2));
|
|
428
428
|
min-inline-size: var(--ui-badge-dot-size, var(--ui-space-2));
|
|
429
429
|
min-block-size: var(--ui-badge-dot-size, var(--ui-space-2));
|
|
430
|
-
padding: 0;
|
|
430
|
+
padding: 0 !important;
|
|
431
431
|
border-radius: var(--ui-radius-round);
|
|
432
432
|
text-box-trim: none;
|
|
433
433
|
}
|
|
@@ -451,7 +451,7 @@
|
|
|
451
451
|
border-color: transparent;
|
|
452
452
|
border-radius: 0;
|
|
453
453
|
background: var(--ui-badge-border, var(--_badge-color-border, var(--_badge-border)));
|
|
454
|
-
padding-inline-end: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));
|
|
454
|
+
padding-inline-end: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point)) !important;
|
|
455
455
|
clip-path: polygon(0 0, calc(100% - var(--_badge-point)) 0, 100% 50%, calc(100% - var(--_badge-point)) 100%, 0 100%);
|
|
456
456
|
}
|
|
457
457
|
|
|
@@ -470,8 +470,8 @@
|
|
|
470
470
|
}
|
|
471
471
|
|
|
472
472
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=tag"]:dir(rtl) {
|
|
473
|
-
padding-inline-end: var(--ui-badge-padding-inline, var(--ui-space-2));
|
|
474
|
-
padding-inline-start: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));
|
|
473
|
+
padding-inline-end: var(--ui-badge-padding-inline, var(--ui-space-2)) !important;
|
|
474
|
+
padding-inline-start: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point)) !important;
|
|
475
475
|
clip-path: polygon(var(--_badge-point) 0, 100% 0, 100% 100%, var(--_badge-point) 100%, 0 50%);
|
|
476
476
|
}
|
|
477
477
|
|
|
@@ -499,7 +499,7 @@
|
|
|
499
499
|
|
|
500
500
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
501
501
|
:scope:where([data-component~="ui-badge"])[hidden] {
|
|
502
|
-
display: none;
|
|
502
|
+
display: none !important;
|
|
503
503
|
}
|
|
504
504
|
}
|
|
505
505
|
@scope ([data-component~="ui-badge"]) to ([data-component]) {
|
|
@@ -511,7 +511,7 @@
|
|
|
511
511
|
/* Icon content has its own flex item so label ellipsis never clips its strokes. */
|
|
512
512
|
|
|
513
513
|
.icon :where([data-slotted], [data-slotted] *):is(svg) {
|
|
514
|
-
display: block;
|
|
514
|
+
display: block !important;
|
|
515
515
|
inline-size: 1em;
|
|
516
516
|
block-size: 1em;
|
|
517
517
|
flex: none;
|
|
@@ -522,7 +522,7 @@
|
|
|
522
522
|
inline-size: 1em;
|
|
523
523
|
block-size: 1em;
|
|
524
524
|
vertical-align: middle;
|
|
525
|
-
margin-inline-end: var(--ui-space-1);
|
|
525
|
+
margin-inline-end: var(--ui-space-1) !important;
|
|
526
526
|
}
|
|
527
527
|
|
|
528
528
|
/* Center the capital/baseline text box, while clipping only inline overflow for ellipsis.
|
|
@@ -548,13 +548,13 @@
|
|
|
548
548
|
/* An icon mark keeps the existing tone recipe and follows the global spacing and radius. */
|
|
549
549
|
|
|
550
550
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=square"] .label :where([data-slotted], [data-slotted] *):is(svg) {
|
|
551
|
-
margin-inline-end: 0;
|
|
551
|
+
margin-inline-end: 0 !important;
|
|
552
552
|
}
|
|
553
553
|
|
|
554
554
|
/* A visible glyph needs fixed geometry, unlike a content-sized pill or a hidden-label dot. */
|
|
555
555
|
|
|
556
556
|
:scope:where([data-component~="ui-badge"])[data-ui-badge-state~="shape=circle"] .label :where([data-slotted], [data-slotted] *):is(svg) {
|
|
557
|
-
margin-inline-end: 0;
|
|
557
|
+
margin-inline-end: 0 !important;
|
|
558
558
|
}
|
|
559
559
|
|
|
560
560
|
/* Center capital and numeral ink, rather than the font's ascent/descent line box.
|