@pithyjs/ui-kit 0.1.0-beta.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/LICENSE +21 -0
- package/dist/animation/animate-in.d.ts +35 -0
- package/dist/animation/animate-in.d.ts.map +1 -0
- package/dist/animation/animate-in.js +71 -0
- package/dist/animation/animate-in.js.map +1 -0
- package/dist/atoms/actions/_icon-control.scss +53 -0
- package/dist/atoms/actions/button/Button.d.ts +93 -0
- package/dist/atoms/actions/button/Button.d.ts.map +1 -0
- package/dist/atoms/actions/button/Button.js +332 -0
- package/dist/atoms/actions/button/Button.js.map +1 -0
- package/dist/atoms/actions/button/button.scss +342 -0
- package/dist/atoms/actions/icon-button/IconButton.d.ts +47 -0
- package/dist/atoms/actions/icon-button/IconButton.d.ts.map +1 -0
- package/dist/atoms/actions/icon-button/IconButton.js +81 -0
- package/dist/atoms/actions/icon-button/IconButton.js.map +1 -0
- package/dist/atoms/actions/icon-button/icon-button.scss +20 -0
- package/dist/atoms/actions/icon-group/IconGroup.d.ts +60 -0
- package/dist/atoms/actions/icon-group/IconGroup.d.ts.map +1 -0
- package/dist/atoms/actions/icon-group/IconGroup.js +191 -0
- package/dist/atoms/actions/icon-group/IconGroup.js.map +1 -0
- package/dist/atoms/actions/icon-group/icon-group.scss +36 -0
- package/dist/atoms/actions/segmented-control/SegmentedControl.d.ts +49 -0
- package/dist/atoms/actions/segmented-control/SegmentedControl.d.ts.map +1 -0
- package/dist/atoms/actions/segmented-control/SegmentedControl.js +107 -0
- package/dist/atoms/actions/segmented-control/SegmentedControl.js.map +1 -0
- package/dist/atoms/actions/segmented-control/segmented-control.scss +90 -0
- package/dist/atoms/content/_mixins.scss +79 -0
- package/dist/atoms/content/action-tile/ActionTile.d.ts +27 -0
- package/dist/atoms/content/action-tile/ActionTile.d.ts.map +1 -0
- package/dist/atoms/content/action-tile/ActionTile.js +98 -0
- package/dist/atoms/content/action-tile/ActionTile.js.map +1 -0
- package/dist/atoms/content/action-tile/action-tile.scss +150 -0
- package/dist/atoms/content/badge/Badge.d.ts +57 -0
- package/dist/atoms/content/badge/Badge.d.ts.map +1 -0
- package/dist/atoms/content/badge/Badge.js +177 -0
- package/dist/atoms/content/badge/Badge.js.map +1 -0
- package/dist/atoms/content/badge/badge.scss +198 -0
- package/dist/atoms/content/heading/Heading.d.ts +53 -0
- package/dist/atoms/content/heading/Heading.d.ts.map +1 -0
- package/dist/atoms/content/heading/Heading.js +142 -0
- package/dist/atoms/content/heading/Heading.js.map +1 -0
- package/dist/atoms/content/heading/heading.scss +43 -0
- package/dist/atoms/content/icon/Icon.d.ts +68 -0
- package/dist/atoms/content/icon/Icon.d.ts.map +1 -0
- package/dist/atoms/content/icon/Icon.js +137 -0
- package/dist/atoms/content/icon/Icon.js.map +1 -0
- package/dist/atoms/content/icon/icon.scss +66 -0
- package/dist/atoms/content/icon/resolveIconSvg.d.ts +21 -0
- package/dist/atoms/content/icon/resolveIconSvg.d.ts.map +1 -0
- package/dist/atoms/content/icon/resolveIconSvg.js +73 -0
- package/dist/atoms/content/icon/resolveIconSvg.js.map +1 -0
- package/dist/atoms/content/image/Image.d.ts +81 -0
- package/dist/atoms/content/image/Image.d.ts.map +1 -0
- package/dist/atoms/content/image/Image.js +293 -0
- package/dist/atoms/content/image/Image.js.map +1 -0
- package/dist/atoms/content/image/image.scss +77 -0
- package/dist/atoms/content/text/Text.d.ts +58 -0
- package/dist/atoms/content/text/Text.d.ts.map +1 -0
- package/dist/atoms/content/text/Text.js +158 -0
- package/dist/atoms/content/text/Text.js.map +1 -0
- package/dist/atoms/content/text/text.scss +98 -0
- package/dist/atoms/content/tile/Tile.d.ts +66 -0
- package/dist/atoms/content/tile/Tile.d.ts.map +1 -0
- package/dist/atoms/content/tile/Tile.js +125 -0
- package/dist/atoms/content/tile/Tile.js.map +1 -0
- package/dist/atoms/content/tile/tile.scss +122 -0
- package/dist/atoms/feedback/tooltip/Tooltip.d.ts +44 -0
- package/dist/atoms/feedback/tooltip/Tooltip.d.ts.map +1 -0
- package/dist/atoms/feedback/tooltip/Tooltip.js +121 -0
- package/dist/atoms/feedback/tooltip/Tooltip.js.map +1 -0
- package/dist/atoms/feedback/tooltip/tooltip.scss +96 -0
- package/dist/atoms/forms/checkbox/Checkbox.d.ts +49 -0
- package/dist/atoms/forms/checkbox/Checkbox.d.ts.map +1 -0
- package/dist/atoms/forms/checkbox/Checkbox.js +269 -0
- package/dist/atoms/forms/checkbox/Checkbox.js.map +1 -0
- package/dist/atoms/forms/checkbox/CheckboxGroup.d.ts +50 -0
- package/dist/atoms/forms/checkbox/CheckboxGroup.d.ts.map +1 -0
- package/dist/atoms/forms/checkbox/CheckboxGroup.js +132 -0
- package/dist/atoms/forms/checkbox/CheckboxGroup.js.map +1 -0
- package/dist/atoms/forms/checkbox/checkbox.scss +506 -0
- package/dist/atoms/forms/file-picker/FilePicker.d.ts +23 -0
- package/dist/atoms/forms/file-picker/FilePicker.d.ts.map +1 -0
- package/dist/atoms/forms/file-picker/FilePicker.js +103 -0
- package/dist/atoms/forms/file-picker/FilePicker.js.map +1 -0
- package/dist/atoms/forms/file-picker/file-picker.scss +84 -0
- package/dist/atoms/forms/form-field/FormField.d.ts +39 -0
- package/dist/atoms/forms/form-field/FormField.d.ts.map +1 -0
- package/dist/atoms/forms/form-field/FormField.js +139 -0
- package/dist/atoms/forms/form-field/FormField.js.map +1 -0
- package/dist/atoms/forms/form-field/form-field.scss +46 -0
- package/dist/atoms/forms/input/Input.d.ts +81 -0
- package/dist/atoms/forms/input/Input.d.ts.map +1 -0
- package/dist/atoms/forms/input/Input.js +417 -0
- package/dist/atoms/forms/input/Input.js.map +1 -0
- package/dist/atoms/forms/input/input.scss +547 -0
- package/dist/atoms/forms/radio/Radio.d.ts +54 -0
- package/dist/atoms/forms/radio/Radio.d.ts.map +1 -0
- package/dist/atoms/forms/radio/Radio.js +278 -0
- package/dist/atoms/forms/radio/Radio.js.map +1 -0
- package/dist/atoms/forms/radio/RadioGroup.d.ts +54 -0
- package/dist/atoms/forms/radio/RadioGroup.d.ts.map +1 -0
- package/dist/atoms/forms/radio/RadioGroup.js +137 -0
- package/dist/atoms/forms/radio/RadioGroup.js.map +1 -0
- package/dist/atoms/forms/radio/radio.scss +459 -0
- package/dist/atoms/forms/select/Select.d.ts +57 -0
- package/dist/atoms/forms/select/Select.d.ts.map +1 -0
- package/dist/atoms/forms/select/Select.js +457 -0
- package/dist/atoms/forms/select/Select.js.map +1 -0
- package/dist/atoms/forms/select/select-dropdown.d.ts +49 -0
- package/dist/atoms/forms/select/select-dropdown.d.ts.map +1 -0
- package/dist/atoms/forms/select/select-dropdown.js +305 -0
- package/dist/atoms/forms/select/select-dropdown.js.map +1 -0
- package/dist/atoms/forms/select/select-keyboard.d.ts +14 -0
- package/dist/atoms/forms/select/select-keyboard.d.ts.map +1 -0
- package/dist/atoms/forms/select/select-keyboard.js +182 -0
- package/dist/atoms/forms/select/select-keyboard.js.map +1 -0
- package/dist/atoms/forms/select/select.scss +630 -0
- package/dist/atoms/forms/textarea/Textarea.d.ts +69 -0
- package/dist/atoms/forms/textarea/Textarea.d.ts.map +1 -0
- package/dist/atoms/forms/textarea/Textarea.js +394 -0
- package/dist/atoms/forms/textarea/Textarea.js.map +1 -0
- package/dist/atoms/forms/textarea/textarea.scss +486 -0
- package/dist/atoms/forms/toggle/Toggle.d.ts +47 -0
- package/dist/atoms/forms/toggle/Toggle.d.ts.map +1 -0
- package/dist/atoms/forms/toggle/Toggle.js +243 -0
- package/dist/atoms/forms/toggle/Toggle.js.map +1 -0
- package/dist/atoms/forms/toggle/toggle.scss +561 -0
- package/dist/compiler.d.ts +7 -0
- package/dist/compiler.d.ts.map +1 -0
- package/dist/compiler.js +18 -0
- package/dist/compiler.js.map +1 -0
- package/dist/icons/index.d.ts +14 -0
- package/dist/icons/index.d.ts.map +1 -0
- package/dist/icons/index.js +14 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/icons/registry.d.ts +65 -0
- package/dist/icons/registry.d.ts.map +1 -0
- package/dist/icons/registry.js +126 -0
- package/dist/icons/registry.js.map +1 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/Grid.d.ts +78 -0
- package/dist/layout/Grid.d.ts.map +1 -0
- package/dist/layout/Grid.js +272 -0
- package/dist/layout/Grid.js.map +1 -0
- package/dist/layout/GridItem.d.ts +52 -0
- package/dist/layout/GridItem.d.ts.map +1 -0
- package/dist/layout/GridItem.js +99 -0
- package/dist/layout/GridItem.js.map +1 -0
- package/dist/layout/PageSection.d.ts +43 -0
- package/dist/layout/PageSection.d.ts.map +1 -0
- package/dist/layout/PageSection.js +75 -0
- package/dist/layout/PageSection.js.map +1 -0
- package/dist/layout/SmartContainer.d.ts +66 -0
- package/dist/layout/SmartContainer.d.ts.map +1 -0
- package/dist/layout/SmartContainer.js +194 -0
- package/dist/layout/SmartContainer.js.map +1 -0
- package/dist/layout/Stack.d.ts +65 -0
- package/dist/layout/Stack.d.ts.map +1 -0
- package/dist/layout/Stack.js +114 -0
- package/dist/layout/Stack.js.map +1 -0
- package/dist/organisms/content/Card.d.ts +93 -0
- package/dist/organisms/content/Card.d.ts.map +1 -0
- package/dist/organisms/content/Card.js +353 -0
- package/dist/organisms/content/Card.js.map +1 -0
- package/dist/organisms/content/_card-horizontal.scss +88 -0
- package/dist/organisms/content/_card-link.scss +49 -0
- package/dist/organisms/content/_card-overlay.scss +91 -0
- package/dist/organisms/content/_card-root.scss +99 -0
- package/dist/organisms/content/_card-slots.scss +143 -0
- package/dist/organisms/content/_card-states.scss +166 -0
- package/dist/organisms/content/_card-tokens.scss +22 -0
- package/dist/organisms/content/_card-variants.scss +31 -0
- package/dist/organisms/content/card.scss +15 -0
- package/dist/organisms/feedback/Modal.d.ts +39 -0
- package/dist/organisms/feedback/Modal.d.ts.map +1 -0
- package/dist/organisms/feedback/Modal.js +120 -0
- package/dist/organisms/feedback/Modal.js.map +1 -0
- package/dist/organisms/feedback/Popover.d.ts +30 -0
- package/dist/organisms/feedback/Popover.d.ts.map +1 -0
- package/dist/organisms/feedback/Popover.js +151 -0
- package/dist/organisms/feedback/Popover.js.map +1 -0
- package/dist/organisms/feedback/modal.scss +66 -0
- package/dist/organisms/feedback/popover.scss +27 -0
- package/dist/organisms/forms/DynamicForm.d.ts +118 -0
- package/dist/organisms/forms/DynamicForm.d.ts.map +1 -0
- package/dist/organisms/forms/DynamicForm.js +546 -0
- package/dist/organisms/forms/DynamicForm.js.map +1 -0
- package/dist/organisms/forms/Form.d.ts +62 -0
- package/dist/organisms/forms/Form.d.ts.map +1 -0
- package/dist/organisms/forms/Form.js +131 -0
- package/dist/organisms/forms/Form.js.map +1 -0
- package/dist/organisms/forms/dynamic-form.scss +91 -0
- package/dist/organisms/forms/form-helpers.d.ts +21 -0
- package/dist/organisms/forms/form-helpers.d.ts.map +1 -0
- package/dist/organisms/forms/form-helpers.js +57 -0
- package/dist/organisms/forms/form-helpers.js.map +1 -0
- package/dist/organisms/forms/form-state.d.ts +66 -0
- package/dist/organisms/forms/form-state.d.ts.map +1 -0
- package/dist/organisms/forms/form-state.js +156 -0
- package/dist/organisms/forms/form-state.js.map +1 -0
- package/dist/organisms/forms/form.scss +23 -0
- package/dist/organisms/forms/validation.d.ts +32 -0
- package/dist/organisms/forms/validation.d.ts.map +1 -0
- package/dist/organisms/forms/validation.js +118 -0
- package/dist/organisms/forms/validation.js.map +1 -0
- package/dist/organisms/navigation/Navbar.d.ts +66 -0
- package/dist/organisms/navigation/Navbar.d.ts.map +1 -0
- package/dist/organisms/navigation/Navbar.js +881 -0
- package/dist/organisms/navigation/Navbar.js.map +1 -0
- package/dist/organisms/navigation/_navbar-announcement.scss +62 -0
- package/dist/organisms/navigation/_navbar-brand.scss +69 -0
- package/dist/organisms/navigation/_navbar-container.scss +37 -0
- package/dist/organisms/navigation/_navbar-desktop.scss +116 -0
- package/dist/organisms/navigation/_navbar-drawer.scss +97 -0
- package/dist/organisms/navigation/_navbar-links.scss +143 -0
- package/dist/organisms/navigation/_navbar-menu.scss +193 -0
- package/dist/organisms/navigation/_navbar-root.scss +107 -0
- package/dist/organisms/navigation/_navbar-search.scss +83 -0
- package/dist/organisms/navigation/_navbar-toggle.scss +91 -0
- package/dist/organisms/navigation/_navbar-tokens.scss +15 -0
- package/dist/organisms/navigation/navbar.scss +17 -0
- package/dist/registry/categories.d.ts +6 -0
- package/dist/registry/categories.d.ts.map +1 -0
- package/dist/registry/categories.js +13 -0
- package/dist/registry/categories.js.map +1 -0
- package/dist/registry/components.d.ts +5 -0
- package/dist/registry/components.d.ts.map +1 -0
- package/dist/registry/components.js +95 -0
- package/dist/registry/components.js.map +1 -0
- package/dist/registry/index.d.ts +59 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +79 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/levels.d.ts +6 -0
- package/dist/registry/levels.d.ts.map +1 -0
- package/dist/registry/levels.js +9 -0
- package/dist/registry/levels.js.map +1 -0
- package/dist/registry/registry-meta-types.d.ts +67 -0
- package/dist/registry/registry-meta-types.d.ts.map +1 -0
- package/dist/registry/registry-meta-types.js +6 -0
- package/dist/registry/registry-meta-types.js.map +1 -0
- package/dist/registry/registry-meta.d.ts +5 -0
- package/dist/registry/registry-meta.d.ts.map +1 -0
- package/dist/registry/registry-meta.js +731 -0
- package/dist/registry/registry-meta.js.map +1 -0
- package/dist/registry/renderer.d.ts +69 -0
- package/dist/registry/renderer.d.ts.map +1 -0
- package/dist/registry/renderer.js +311 -0
- package/dist/registry/renderer.js.map +1 -0
- package/dist/sections/_section-base.scss +204 -0
- package/dist/sections/contact/ContactSection.d.ts +55 -0
- package/dist/sections/contact/ContactSection.d.ts.map +1 -0
- package/dist/sections/contact/ContactSection.js +142 -0
- package/dist/sections/contact/ContactSection.js.map +1 -0
- package/dist/sections/contact/contact-section.scss +142 -0
- package/dist/sections/cta/CTASection.d.ts +52 -0
- package/dist/sections/cta/CTASection.d.ts.map +1 -0
- package/dist/sections/cta/CTASection.js +130 -0
- package/dist/sections/cta/CTASection.js.map +1 -0
- package/dist/sections/cta/cta-section.scss +131 -0
- package/dist/sections/entrance.d.ts +29 -0
- package/dist/sections/entrance.d.ts.map +1 -0
- package/dist/sections/entrance.js +69 -0
- package/dist/sections/entrance.js.map +1 -0
- package/dist/sections/features/FeaturesSection.d.ts +54 -0
- package/dist/sections/features/FeaturesSection.d.ts.map +1 -0
- package/dist/sections/features/FeaturesSection.js +139 -0
- package/dist/sections/features/FeaturesSection.js.map +1 -0
- package/dist/sections/features/features-section.scss +140 -0
- package/dist/sections/footer/FooterSection.d.ts +53 -0
- package/dist/sections/footer/FooterSection.d.ts.map +1 -0
- package/dist/sections/footer/FooterSection.js +147 -0
- package/dist/sections/footer/FooterSection.js.map +1 -0
- package/dist/sections/footer/footer-section.scss +131 -0
- package/dist/sections/hero/HeroSection.d.ts +66 -0
- package/dist/sections/hero/HeroSection.d.ts.map +1 -0
- package/dist/sections/hero/HeroSection.js +156 -0
- package/dist/sections/hero/HeroSection.js.map +1 -0
- package/dist/sections/hero/hero-section.scss +211 -0
- package/dist/shared/_form-animations.scss +283 -0
- package/dist/shared/_media-fit.scss +63 -0
- package/dist/shared/_mixins.scss +69 -0
- package/dist/shared/_tokens.scss +116 -0
- package/dist/shared/badge.d.ts +15 -0
- package/dist/shared/badge.d.ts.map +1 -0
- package/dist/shared/badge.js +15 -0
- package/dist/shared/badge.js.map +1 -0
- package/dist/shared/button.d.ts +22 -0
- package/dist/shared/button.d.ts.map +1 -0
- package/dist/shared/button.js +22 -0
- package/dist/shared/button.js.map +1 -0
- package/dist/shared/card.d.ts +21 -0
- package/dist/shared/card.d.ts.map +1 -0
- package/dist/shared/card.js +38 -0
- package/dist/shared/card.js.map +1 -0
- package/dist/shared/checkbox.d.ts +10 -0
- package/dist/shared/checkbox.d.ts.map +1 -0
- package/dist/shared/checkbox.js +28 -0
- package/dist/shared/checkbox.js.map +1 -0
- package/dist/shared/clickable.d.ts +34 -0
- package/dist/shared/clickable.d.ts.map +1 -0
- package/dist/shared/clickable.js +54 -0
- package/dist/shared/clickable.js.map +1 -0
- package/dist/shared/common.d.ts +31 -0
- package/dist/shared/common.d.ts.map +1 -0
- package/dist/shared/common.js +92 -0
- package/dist/shared/common.js.map +1 -0
- package/dist/shared/entrance-config.d.ts +46 -0
- package/dist/shared/entrance-config.d.ts.map +1 -0
- package/dist/shared/entrance-config.js +54 -0
- package/dist/shared/entrance-config.js.map +1 -0
- package/dist/shared/focusable.d.ts +8 -0
- package/dist/shared/focusable.d.ts.map +1 -0
- package/dist/shared/focusable.js +17 -0
- package/dist/shared/focusable.js.map +1 -0
- package/dist/shared/form-elements.d.ts +57 -0
- package/dist/shared/form-elements.d.ts.map +1 -0
- package/dist/shared/form-elements.js +95 -0
- package/dist/shared/form-elements.js.map +1 -0
- package/dist/shared/form-state.d.ts +52 -0
- package/dist/shared/form-state.d.ts.map +1 -0
- package/dist/shared/form-state.js +151 -0
- package/dist/shared/form-state.js.map +1 -0
- package/dist/shared/grid.d.ts +21 -0
- package/dist/shared/grid.d.ts.map +1 -0
- package/dist/shared/grid.js +187 -0
- package/dist/shared/grid.js.map +1 -0
- package/dist/shared/icon-slot.d.ts +22 -0
- package/dist/shared/icon-slot.d.ts.map +1 -0
- package/dist/shared/icon-slot.js +38 -0
- package/dist/shared/icon-slot.js.map +1 -0
- package/dist/shared/icon.d.ts +17 -0
- package/dist/shared/icon.d.ts.map +1 -0
- package/dist/shared/icon.js +18 -0
- package/dist/shared/icon.js.map +1 -0
- package/dist/shared/icons.d.ts +19 -0
- package/dist/shared/icons.d.ts.map +1 -0
- package/dist/shared/icons.js +22 -0
- package/dist/shared/icons.js.map +1 -0
- package/dist/shared/image.d.ts +35 -0
- package/dist/shared/image.d.ts.map +1 -0
- package/dist/shared/image.js +46 -0
- package/dist/shared/image.js.map +1 -0
- package/dist/shared/input.d.ts +12 -0
- package/dist/shared/input.d.ts.map +1 -0
- package/dist/shared/input.js +29 -0
- package/dist/shared/input.js.map +1 -0
- package/dist/shared/radio.d.ts +10 -0
- package/dist/shared/radio.d.ts.map +1 -0
- package/dist/shared/radio.js +29 -0
- package/dist/shared/radio.js.map +1 -0
- package/dist/shared/reconcile-list.d.ts +37 -0
- package/dist/shared/reconcile-list.d.ts.map +1 -0
- package/dist/shared/reconcile-list.js +95 -0
- package/dist/shared/reconcile-list.js.map +1 -0
- package/dist/shared/section.d.ts +23 -0
- package/dist/shared/section.d.ts.map +1 -0
- package/dist/shared/section.js +65 -0
- package/dist/shared/section.js.map +1 -0
- package/dist/shared/segmented.d.ts +17 -0
- package/dist/shared/segmented.d.ts.map +1 -0
- package/dist/shared/segmented.js +53 -0
- package/dist/shared/segmented.js.map +1 -0
- package/dist/shared/select.d.ts +18 -0
- package/dist/shared/select.d.ts.map +1 -0
- package/dist/shared/select.js +14 -0
- package/dist/shared/select.js.map +1 -0
- package/dist/shared/slots.d.ts +11 -0
- package/dist/shared/slots.d.ts.map +1 -0
- package/dist/shared/slots.js +33 -0
- package/dist/shared/slots.js.map +1 -0
- package/dist/shared/smart-container.d.ts +19 -0
- package/dist/shared/smart-container.d.ts.map +1 -0
- package/dist/shared/smart-container.js +29 -0
- package/dist/shared/smart-container.js.map +1 -0
- package/dist/shared/text.d.ts +29 -0
- package/dist/shared/text.d.ts.map +1 -0
- package/dist/shared/text.js +72 -0
- package/dist/shared/text.js.map +1 -0
- package/dist/shared/textarea.d.ts +6 -0
- package/dist/shared/textarea.d.ts.map +1 -0
- package/dist/shared/textarea.js +18 -0
- package/dist/shared/textarea.js.map +1 -0
- package/dist/shared/toggle.d.ts +6 -0
- package/dist/shared/toggle.d.ts.map +1 -0
- package/dist/shared/toggle.js +19 -0
- package/dist/shared/toggle.js.map +1 -0
- package/dist/shared/types.d.ts +41 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +20 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/structural/ErrorBoundary.d.ts +18 -0
- package/dist/structural/ErrorBoundary.d.ts.map +1 -0
- package/dist/structural/ErrorBoundary.js +119 -0
- package/dist/structural/ErrorBoundary.js.map +1 -0
- package/dist/structural/For.d.ts +37 -0
- package/dist/structural/For.d.ts.map +1 -0
- package/dist/structural/For.js +129 -0
- package/dist/structural/For.js.map +1 -0
- package/dist/structural/Lazy.d.ts +43 -0
- package/dist/structural/Lazy.d.ts.map +1 -0
- package/dist/structural/Lazy.js +47 -0
- package/dist/structural/Lazy.js.map +1 -0
- package/dist/structural/NavLink.d.ts +45 -0
- package/dist/structural/NavLink.d.ts.map +1 -0
- package/dist/structural/NavLink.js +37 -0
- package/dist/structural/NavLink.js.map +1 -0
- package/dist/structural/Show.d.ts +35 -0
- package/dist/structural/Show.d.ts.map +1 -0
- package/dist/structural/Show.js +34 -0
- package/dist/structural/Show.js.map +1 -0
- package/dist/structural/nav-link.scss +54 -0
- package/dist/styles/index.scss +58 -0
- package/package.json +64 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/// Card root article + layout wrapper
|
|
2
|
+
/// @group organisms/content
|
|
3
|
+
|
|
4
|
+
@use '@pithyjs/design-system/a11y/styles/mixins' as a11y;
|
|
5
|
+
@use '../../shared/tokens' as shared;
|
|
6
|
+
|
|
7
|
+
// ============================================
|
|
8
|
+
// Root (the <article>) — carries chrome + acts as the query container
|
|
9
|
+
// ============================================
|
|
10
|
+
|
|
11
|
+
.ui-card {
|
|
12
|
+
// Component-scoped tokens — every variant mutates these, never the global
|
|
13
|
+
// design-system primitives. Defaults match variant="default".
|
|
14
|
+
--_card-bg: var(--color-surface);
|
|
15
|
+
--_card-border-color: var(--color-border);
|
|
16
|
+
--_card-shadow: var(--shadow-xs);
|
|
17
|
+
--_card-radius: var(--radius-md);
|
|
18
|
+
--_card-padding: var(--space-md);
|
|
19
|
+
|
|
20
|
+
// Every card is a query container. `.ui-card-layout` (a descendant) uses
|
|
21
|
+
// @container to switch between vertical and horizontal layouts based on
|
|
22
|
+
// the card's own inline-size. An element cannot query itself — hence the
|
|
23
|
+
// nested layout wrapper.
|
|
24
|
+
container-type: inline-size;
|
|
25
|
+
// container-type: inline-size implies contain: inline-size layout style.
|
|
26
|
+
// We add paint containment explicitly for repaint isolation.
|
|
27
|
+
contain: layout paint;
|
|
28
|
+
|
|
29
|
+
position: relative;
|
|
30
|
+
isolation: isolate;
|
|
31
|
+
|
|
32
|
+
display: block;
|
|
33
|
+
inline-size: 100%;
|
|
34
|
+
min-inline-size: 0;
|
|
35
|
+
|
|
36
|
+
background-color: var(--_card-bg);
|
|
37
|
+
border: var(--border-width-hairline) solid var(--_card-border-color);
|
|
38
|
+
border-radius: var(--_card-radius);
|
|
39
|
+
box-shadow: var(--_card-shadow);
|
|
40
|
+
// Padding lives on `.ui-card-layout`, not on the article — both the
|
|
41
|
+
// layout's padding AND the media's negative-inset margin must resolve
|
|
42
|
+
// against the SAME container-query context. Since `--space-*` tokens
|
|
43
|
+
// use `cqw`, and the card is a query container (`container-type:
|
|
44
|
+
// inline-size`), the article's own `cqw` queries the OUTER container
|
|
45
|
+
// while descendants query the card. Keeping padding on the layout keeps
|
|
46
|
+
// both values in sync so media bleed aligns pixel-perfect.
|
|
47
|
+
|
|
48
|
+
color: var(--color-text);
|
|
49
|
+
|
|
50
|
+
@include a11y.motion-safe {
|
|
51
|
+
transition:
|
|
52
|
+
var(--motion-transition-background),
|
|
53
|
+
var(--motion-transition-border),
|
|
54
|
+
var(--motion-transition-shadow),
|
|
55
|
+
translate var(--motion-duration-normal) var(--motion-easing-standard);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ============================================
|
|
60
|
+
// Layout wrapper — the flex/grid root
|
|
61
|
+
// ============================================
|
|
62
|
+
|
|
63
|
+
.ui-card-layout {
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
gap: var(--space-sm);
|
|
67
|
+
min-inline-size: 0;
|
|
68
|
+
// Pass through the card's radius so nested slots that use
|
|
69
|
+
// `border-radius: inherit` (media, caption) resolve correctly.
|
|
70
|
+
border-radius: inherit;
|
|
71
|
+
// Padding belongs here (not on the article) so the value resolves against
|
|
72
|
+
// the same container-query context the media's negative-inset margin uses.
|
|
73
|
+
// Both read the card's inline-size, not the outer container's.
|
|
74
|
+
padding: var(--_card-padding);
|
|
75
|
+
// No `z-index` here on purpose — that would create a stacking context and
|
|
76
|
+
// trap interactive descendants' z-index below the pseudo-link overlay.
|
|
77
|
+
// Tree-order keeps layout below .ui-card-link (which comes after it in
|
|
78
|
+
// the DOM) and layout's descendants can freely raise above the link.
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ============================================
|
|
82
|
+
// Padding + Radius — mirror shared control sizes
|
|
83
|
+
// ============================================
|
|
84
|
+
|
|
85
|
+
@each $size in shared.$control-sizes {
|
|
86
|
+
.ui-card[data-padding='#{$size}'] {
|
|
87
|
+
--_card-padding: var(--space-#{$size});
|
|
88
|
+
}
|
|
89
|
+
.ui-card[data-radius='#{$size}'] {
|
|
90
|
+
--_card-radius: var(--radius-#{$size});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.ui-card[data-padding='none'] {
|
|
95
|
+
--_card-padding: 0;
|
|
96
|
+
}
|
|
97
|
+
.ui-card[data-radius='none'] {
|
|
98
|
+
--_card-radius: 0;
|
|
99
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/// Card slot styles — media, header, body, footer, eyebrow
|
|
2
|
+
/// @group organisms/content
|
|
3
|
+
|
|
4
|
+
@use 'sass:map';
|
|
5
|
+
@use '@pithyjs/design-system/a11y/styles/mixins' as a11y;
|
|
6
|
+
@use '@pithyjs/design-system/typography/_generated/tokens' as typo;
|
|
7
|
+
@use '../../shared/tokens' as shared;
|
|
8
|
+
|
|
9
|
+
// ============================================
|
|
10
|
+
// Slots — media / header / body / footer
|
|
11
|
+
// ============================================
|
|
12
|
+
|
|
13
|
+
.ui-card-media {
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
border-radius: inherit;
|
|
16
|
+
inline-size: 100%;
|
|
17
|
+
max-block-size: shared.$card-media-max-block;
|
|
18
|
+
|
|
19
|
+
> * {
|
|
20
|
+
display: block;
|
|
21
|
+
inline-size: 100%;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:where(img, video, picture, iframe, canvas) {
|
|
25
|
+
display: block;
|
|
26
|
+
inline-size: 100%;
|
|
27
|
+
block-size: auto;
|
|
28
|
+
max-block-size: shared.$card-media-max-block;
|
|
29
|
+
object-fit: contain;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// An explicit aspect ratio locks the media box and crops to fill it.
|
|
34
|
+
.ui-card-media[data-aspect] {
|
|
35
|
+
> * {
|
|
36
|
+
block-size: 100%;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:where(img, video, picture, iframe, canvas) {
|
|
40
|
+
block-size: 100%;
|
|
41
|
+
object-fit: cover;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Vertical mode media bleed — negative-inset so media kisses the card's
|
|
46
|
+
// inline + top edges while body padding below remains. The `data-orientation`
|
|
47
|
+
// default is "vertical"; horizontal is handled inside the @container block.
|
|
48
|
+
.ui-card[data-orientation='vertical']:not([data-padding='none'])
|
|
49
|
+
.ui-card-media {
|
|
50
|
+
margin-block-start: calc(-1 * var(--_card-padding));
|
|
51
|
+
margin-inline: calc(-1 * var(--_card-padding));
|
|
52
|
+
inline-size: calc(100% + 2 * var(--_card-padding));
|
|
53
|
+
max-inline-size: none;
|
|
54
|
+
border-start-start-radius: inherit;
|
|
55
|
+
border-start-end-radius: inherit;
|
|
56
|
+
border-end-start-radius: 0;
|
|
57
|
+
border-end-end-radius: 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Media → header/body gap boost — the layout's flex `gap: --space-sm` is
|
|
61
|
+
// Close Friends spacing (great for header↔body), but a full-bleed image is a
|
|
62
|
+
// distinct content cluster from the text block below it: Friends spacing
|
|
63
|
+
// (--space-md). We supplement the flex gap so the total visual gap equals
|
|
64
|
+
// --space-md without disturbing header↔body.
|
|
65
|
+
.ui-card[data-orientation='vertical'] .ui-card-media + .ui-card-header,
|
|
66
|
+
.ui-card[data-orientation='vertical'] .ui-card-media + .ui-card-body {
|
|
67
|
+
margin-block-start: calc(var(--space-md) - var(--space-sm));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Aspect ratios
|
|
71
|
+
.ui-card-media[data-aspect='1/1'] {
|
|
72
|
+
aspect-ratio: 1 / 1;
|
|
73
|
+
}
|
|
74
|
+
.ui-card-media[data-aspect='4/3'] {
|
|
75
|
+
aspect-ratio: 4 / 3;
|
|
76
|
+
}
|
|
77
|
+
.ui-card-media[data-aspect='16/9'] {
|
|
78
|
+
aspect-ratio: 16 / 9;
|
|
79
|
+
}
|
|
80
|
+
.ui-card-media[data-aspect='3/2'] {
|
|
81
|
+
aspect-ratio: 3 / 2;
|
|
82
|
+
}
|
|
83
|
+
.ui-card-media[data-aspect='21/9'] {
|
|
84
|
+
aspect-ratio: 21 / 9;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.ui-card-header {
|
|
88
|
+
display: flex;
|
|
89
|
+
flex-direction: column;
|
|
90
|
+
gap: var(--space-xs); // eyebrow ↔ title ↔ meta: Lovers / Close Friends
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Eyebrow — primary-colored, uppercase, letter-spaced kicker above the
|
|
94
|
+
// heading. Mirrors the .ui-section-eyebrow pattern from section templates
|
|
95
|
+
// so card-in-section consumers read as one editorial voice.
|
|
96
|
+
.ui-card-eyebrow {
|
|
97
|
+
font-size: var(--font-size-xs);
|
|
98
|
+
font-weight: var(--font-weight-semibold);
|
|
99
|
+
letter-spacing: map.get(typo.$letter-spacings, 'widest');
|
|
100
|
+
text-transform: uppercase;
|
|
101
|
+
color: var(--color-primary);
|
|
102
|
+
// Tight rhythm: the eyebrow hugs the heading (Lovers spacing).
|
|
103
|
+
line-height: 1;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Slide-in title underline for clickable cards — telegraphs "this card
|
|
107
|
+
// navigates" on hover/focus-within. Parent-triggered: the card's hover
|
|
108
|
+
// activates the heading's underline, not the heading's own :hover.
|
|
109
|
+
// Only the FIRST heading lights up so multi-heading layouts stay clean.
|
|
110
|
+
.ui-card[data-clickable='true']:not([data-disabled='true'])
|
|
111
|
+
.ui-card-header
|
|
112
|
+
:is(h1, h2, h3, h4, h5, h6):first-of-type {
|
|
113
|
+
display: inline-block;
|
|
114
|
+
max-inline-size: fit-content;
|
|
115
|
+
@include a11y.slide-underline($offset: -0.1em, $self-activate: false);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.ui-card[data-clickable='true']:not([data-disabled='true']):hover
|
|
119
|
+
.ui-card-header
|
|
120
|
+
:is(h1, h2, h3, h4, h5, h6):first-of-type,
|
|
121
|
+
.ui-card[data-clickable='true']:not([data-disabled='true']):focus-within
|
|
122
|
+
.ui-card-header
|
|
123
|
+
:is(h1, h2, h3, h4, h5, h6):first-of-type {
|
|
124
|
+
@include a11y.slide-underline-active;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.ui-card-body {
|
|
128
|
+
display: flex;
|
|
129
|
+
flex-direction: column;
|
|
130
|
+
gap: var(--space-sm); // paragraph rhythm: Close Friends
|
|
131
|
+
min-inline-size: 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.ui-card-footer {
|
|
135
|
+
display: flex;
|
|
136
|
+
flex-wrap: wrap;
|
|
137
|
+
align-items: center;
|
|
138
|
+
gap: var(--space-sm);
|
|
139
|
+
// Pin footer to the block-end of the layout column so grid-arranged cards
|
|
140
|
+
// line up at the base.
|
|
141
|
+
margin-block-start: auto;
|
|
142
|
+
padding-block-start: var(--space-sm);
|
|
143
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/// Card interactive states — hover, selected, disabled, forced-colors, selection
|
|
2
|
+
/// @group organisms/content
|
|
3
|
+
|
|
4
|
+
@use '@pithyjs/design-system/a11y/styles/mixins' as a11y;
|
|
5
|
+
|
|
6
|
+
// ============================================
|
|
7
|
+
// Clickable hover / focus-within matrix
|
|
8
|
+
// ============================================
|
|
9
|
+
|
|
10
|
+
.ui-card[data-clickable='true']:not([data-disabled='true']) {
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
|
|
13
|
+
&:hover,
|
|
14
|
+
&:focus-within {
|
|
15
|
+
--_card-border-color: color-mix(
|
|
16
|
+
in oklch,
|
|
17
|
+
var(--color-primary) 25%,
|
|
18
|
+
var(--color-border)
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
@include a11y.motion-safe {
|
|
22
|
+
translate: 0 calc(-1 * var(--motion-distance-subtle));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Interactive-by-content: cards tagged `data-interactive="true"` at mount
|
|
28
|
+
// because they contain a focusable descendant (button, anchor, form
|
|
29
|
+
// control). The inner control makes the whole card an interaction zone,
|
|
30
|
+
// so hover / focus-within lift the card the same way `data-clickable`
|
|
31
|
+
// does. Static cards (pure content, no focusable children) stay flat —
|
|
32
|
+
// lifting every card on hover cheapens the motion. Selected-state rules
|
|
33
|
+
// below compound `[data-selected="true"]` to win on specificity when a
|
|
34
|
+
// selected card is also hovered.
|
|
35
|
+
.ui-card[data-interactive='true']:not([data-disabled='true']):hover,
|
|
36
|
+
.ui-card[data-interactive='true']:not([data-disabled='true']):focus-within {
|
|
37
|
+
--_card-border-color: color-mix(
|
|
38
|
+
in oklch,
|
|
39
|
+
var(--color-primary) 25%,
|
|
40
|
+
var(--color-border)
|
|
41
|
+
);
|
|
42
|
+
--_card-shadow: var(--shadow-md);
|
|
43
|
+
|
|
44
|
+
@include a11y.motion-safe {
|
|
45
|
+
translate: 0 calc(-1 * var(--motion-distance-subtle));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.ui-card[data-clickable='true']:not(
|
|
50
|
+
[data-disabled='true']
|
|
51
|
+
)[data-variant='default']:hover,
|
|
52
|
+
.ui-card[data-clickable='true']:not(
|
|
53
|
+
[data-disabled='true']
|
|
54
|
+
)[data-variant='default']:focus-within {
|
|
55
|
+
--_card-shadow: var(--shadow-md);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.ui-card[data-clickable='true']:not(
|
|
59
|
+
[data-disabled='true']
|
|
60
|
+
)[data-variant='outlined']:hover,
|
|
61
|
+
.ui-card[data-clickable='true']:not(
|
|
62
|
+
[data-disabled='true']
|
|
63
|
+
)[data-variant='outlined']:focus-within {
|
|
64
|
+
--_card-shadow: var(--shadow-sm);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.ui-card[data-clickable='true']:not(
|
|
68
|
+
[data-disabled='true']
|
|
69
|
+
)[data-variant='elevated']:hover,
|
|
70
|
+
.ui-card[data-clickable='true']:not(
|
|
71
|
+
[data-disabled='true']
|
|
72
|
+
)[data-variant='elevated']:focus-within {
|
|
73
|
+
--_card-shadow: var(--shadow-xl);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.ui-card[data-clickable='true']:not(
|
|
77
|
+
[data-disabled='true']
|
|
78
|
+
)[data-variant='subtle']:hover,
|
|
79
|
+
.ui-card[data-clickable='true']:not(
|
|
80
|
+
[data-disabled='true']
|
|
81
|
+
)[data-variant='subtle']:focus-within {
|
|
82
|
+
--_card-shadow: var(--shadow-sm);
|
|
83
|
+
// Subtle stays flat — prevents list jitter.
|
|
84
|
+
translate: none;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.ui-card[data-clickable='true']:not(
|
|
88
|
+
[data-disabled='true']
|
|
89
|
+
)[data-variant='ghost']:hover,
|
|
90
|
+
.ui-card[data-clickable='true']:not(
|
|
91
|
+
[data-disabled='true']
|
|
92
|
+
)[data-variant='ghost']:focus-within {
|
|
93
|
+
--_card-bg: var(--color-surface-variant);
|
|
94
|
+
--_card-border-color: var(--color-border);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ============================================
|
|
98
|
+
// Selected
|
|
99
|
+
// ============================================
|
|
100
|
+
|
|
101
|
+
.ui-card[data-selected='true'] {
|
|
102
|
+
--_card-selected-ring-width: var(--border-width-thin);
|
|
103
|
+
--_card-border-color: var(--color-primary);
|
|
104
|
+
// Inner ring (belt-and-suspenders emphasis alongside the colored border).
|
|
105
|
+
box-shadow:
|
|
106
|
+
inset 0 0 0 var(--_card-selected-ring-width) var(--color-primary),
|
|
107
|
+
var(--_card-shadow);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Selected cards respond to hover/focus-within even when not `data-clickable` —
|
|
111
|
+
// the inner action button makes every selected card interactive, so the card
|
|
112
|
+
// should telegraph that on pointer/focus: thicker primary ring, richer shadow,
|
|
113
|
+
// subtle lift. `:not([data-disabled="true"])` both guards the disabled case
|
|
114
|
+
// AND raises specificity to match the `[data-interactive="true"]` hover rule
|
|
115
|
+
// above, so the selected treatment wins by rule order when both apply.
|
|
116
|
+
.ui-card[data-selected='true']:not([data-disabled='true']):hover,
|
|
117
|
+
.ui-card[data-selected='true']:not([data-disabled='true']):focus-within {
|
|
118
|
+
--_card-selected-ring-width: var(--border-width-medium);
|
|
119
|
+
--_card-shadow: var(--shadow-lg);
|
|
120
|
+
|
|
121
|
+
@include a11y.motion-safe {
|
|
122
|
+
translate: 0 calc(-1 * var(--motion-distance-subtle));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ============================================
|
|
127
|
+
// Disabled
|
|
128
|
+
// ============================================
|
|
129
|
+
|
|
130
|
+
.ui-card[data-disabled='true'] {
|
|
131
|
+
opacity: var(--state-disabled-opacity);
|
|
132
|
+
cursor: not-allowed;
|
|
133
|
+
// Kill hover motion — inert already blocks interaction, but motion-safe
|
|
134
|
+
// transitions would still fire without this override.
|
|
135
|
+
translate: none;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ============================================
|
|
139
|
+
// Forced colors
|
|
140
|
+
// ============================================
|
|
141
|
+
|
|
142
|
+
@include a11y.forced-colors {
|
|
143
|
+
.ui-card {
|
|
144
|
+
border: 1px solid ButtonText; // stylelint-disable-line scale-unlimited/declaration-strict-value -- CSS system color required
|
|
145
|
+
box-shadow: none;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.ui-card[data-selected='true'] {
|
|
149
|
+
border: 2px solid Highlight; // stylelint-disable-line scale-unlimited/declaration-strict-value -- CSS system color required
|
|
150
|
+
box-shadow: none;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.ui-card-link:focus-visible {
|
|
154
|
+
@include a11y.focus-outline(Highlight);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ============================================
|
|
159
|
+
// Selection tint
|
|
160
|
+
// ============================================
|
|
161
|
+
|
|
162
|
+
.ui-card::selection,
|
|
163
|
+
.ui-card *::selection {
|
|
164
|
+
background-color: color-mix(in oklch, var(--color-primary) 20%, transparent);
|
|
165
|
+
color: var(--color-text);
|
|
166
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// Card internal sizing tokens
|
|
2
|
+
/// Shared by partials that need the horizontal breakpoint and media column values.
|
|
3
|
+
///
|
|
4
|
+
/// @group organisms/content
|
|
5
|
+
|
|
6
|
+
@use 'sass:map';
|
|
7
|
+
@use '@pithyjs/design-system/layout/_generated/tokens' as layout;
|
|
8
|
+
|
|
9
|
+
// Horizontal orientation activates above this container width.
|
|
10
|
+
// Mobile-first: the layout is vertical everywhere until it has room to
|
|
11
|
+
// breathe; at >= $card-horizontal-min it switches to a 2-column grid.
|
|
12
|
+
$card-horizontal-min: map.get(layout.$container-breakpoints, 'sm');
|
|
13
|
+
|
|
14
|
+
// Horizontal-orientation media column — clamp(min, preferred, max).
|
|
15
|
+
// $card-media-min keeps the thumbnail legible on the narrow side of the
|
|
16
|
+
// horizontal range; $card-media-max prevents oversized media in wide
|
|
17
|
+
// cards; $card-media-preferred lets the column scale fluidly between them.
|
|
18
|
+
// Named here (rather than inlined) so sizing stays auditable and the
|
|
19
|
+
// component contract exposes a single source of truth.
|
|
20
|
+
$card-media-min: 8rem;
|
|
21
|
+
$card-media-preferred: 32%;
|
|
22
|
+
$card-media-max: 14rem;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/// Card variant token overrides
|
|
2
|
+
/// @group organisms/content
|
|
3
|
+
|
|
4
|
+
// ============================================
|
|
5
|
+
// Variants — mutate the --_card-* tokens only
|
|
6
|
+
// ============================================
|
|
7
|
+
|
|
8
|
+
.ui-card[data-variant='outlined'] {
|
|
9
|
+
--_card-bg: var(--color-surface);
|
|
10
|
+
--_card-border-color: var(--color-border);
|
|
11
|
+
--_card-shadow: 0 0 transparent;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.ui-card[data-variant='elevated'] {
|
|
15
|
+
--_card-bg: var(--color-surface);
|
|
16
|
+
// Always carry a hairline — shadow is presence, border is edge.
|
|
17
|
+
--_card-border-color: var(--color-border);
|
|
18
|
+
--_card-shadow: var(--shadow-md);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.ui-card[data-variant='subtle'] {
|
|
22
|
+
--_card-bg: var(--color-surface-variant);
|
|
23
|
+
--_card-border-color: var(--color-border);
|
|
24
|
+
--_card-shadow: 0 0 transparent;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.ui-card[data-variant='ghost'] {
|
|
28
|
+
--_card-bg: transparent;
|
|
29
|
+
--_card-border-color: transparent;
|
|
30
|
+
--_card-shadow: 0 0 transparent;
|
|
31
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// Card organism styles
|
|
2
|
+
/// Content container with named slots (media, header, body, footer),
|
|
3
|
+
/// five variants, two orientations, and a pseudo-link overlay for
|
|
4
|
+
/// full-card navigation.
|
|
5
|
+
///
|
|
6
|
+
/// @group organisms/content
|
|
7
|
+
|
|
8
|
+
@forward 'card-tokens';
|
|
9
|
+
@forward 'card-root';
|
|
10
|
+
@forward 'card-variants';
|
|
11
|
+
@forward 'card-slots';
|
|
12
|
+
@forward 'card-horizontal';
|
|
13
|
+
@forward 'card-overlay';
|
|
14
|
+
@forward 'card-link';
|
|
15
|
+
@forward 'card-states';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.ui-kit.modal",
|
|
4
|
+
"title": "<Modal> Dialog Component",
|
|
5
|
+
"category": "feature",
|
|
6
|
+
"risk": "high"
|
|
7
|
+
}
|
|
8
|
+
*/
|
|
9
|
+
import { type Reactive } from '../../shared/clickable';
|
|
10
|
+
/** @codexApi {"parent":"pithy.ui-kit.modal","name":"ModalProps","stability":"stable","signature":"interface ModalProps"} */
|
|
11
|
+
export interface ModalProps {
|
|
12
|
+
open: Reactive<boolean>;
|
|
13
|
+
onClose: () => void;
|
|
14
|
+
/** Accessible name. Used as `aria-label` unless `titleId` is provided. Required. */
|
|
15
|
+
title: string;
|
|
16
|
+
/** Id of a visible title inside the content — wired as `aria-labelledby`. */
|
|
17
|
+
titleId?: string;
|
|
18
|
+
/** Sets `id` on the dialog element — enables `aria-controls` on the trigger. */
|
|
19
|
+
dialogId?: string;
|
|
20
|
+
/** Pick the element that receives initial focus. Defaults to the first focusable. */
|
|
21
|
+
initialFocus?: (dialogEl: HTMLElement) => HTMLElement | null;
|
|
22
|
+
closeOnBackdrop?: boolean;
|
|
23
|
+
closeOnEscape?: boolean;
|
|
24
|
+
backdropClass?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Content factory, re-invoked on every open so the dialog reflects fresh
|
|
27
|
+
* state. When omitted, the template slot (`renderChildren`) is used once.
|
|
28
|
+
*/
|
|
29
|
+
content?: () => {
|
|
30
|
+
el: Node;
|
|
31
|
+
destroy: () => void;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** @codexApi {"parent":"pithy.ui-kit.modal","name":"Modal","stability":"stable","signature":"(props: ModalProps) => { el: HTMLElement; destroy: () => void }"} */
|
|
35
|
+
export declare function Modal(props: ModalProps): {
|
|
36
|
+
el: HTMLElement;
|
|
37
|
+
destroy: () => void;
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=Modal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/organisms/feedback/Modal.ts"],"names":[],"mappings":"AAAA;;;;;;;EAOE;AAIF,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAErE,4HAA4H;AAC5H,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,WAAW,GAAG,IAAI,CAAC;IAC7D,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CACnD;AAED,kKAAkK;AAClK,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG;IACxC,EAAE,EAAE,WAAW,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CA0HA"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.ui-kit.modal",
|
|
4
|
+
"title": "<Modal> Dialog Component",
|
|
5
|
+
"category": "feature",
|
|
6
|
+
"risk": "high"
|
|
7
|
+
}
|
|
8
|
+
*/
|
|
9
|
+
import { renderChildren, FocusTrap } from '@pithyjs/core';
|
|
10
|
+
import { effect } from '@pithyjs/signals';
|
|
11
|
+
import { readReactive } from '../../shared/clickable';
|
|
12
|
+
/** @codexApi {"parent":"pithy.ui-kit.modal","name":"Modal","stability":"stable","signature":"(props: ModalProps) => { el: HTMLElement; destroy: () => void }"} */
|
|
13
|
+
export function Modal(props) {
|
|
14
|
+
const { open, onClose, title, titleId, dialogId, initialFocus, closeOnBackdrop = true, closeOnEscape = true, backdropClass, content, } = props;
|
|
15
|
+
const name = title?.trim() ?? '';
|
|
16
|
+
if (import.meta.env?.DEV && !name && !titleId) {
|
|
17
|
+
console.warn('[<Modal>] `title` is required for an accessible name.');
|
|
18
|
+
}
|
|
19
|
+
const backdrop = document.createElement('div');
|
|
20
|
+
backdrop.className = 'ui-modal-backdrop';
|
|
21
|
+
if (backdropClass)
|
|
22
|
+
backdrop.classList.add(backdropClass);
|
|
23
|
+
backdrop.hidden = true;
|
|
24
|
+
const dialog = document.createElement('div');
|
|
25
|
+
dialog.className = 'ui-modal';
|
|
26
|
+
dialog.setAttribute('role', 'dialog');
|
|
27
|
+
dialog.setAttribute('aria-modal', 'true');
|
|
28
|
+
if (titleId)
|
|
29
|
+
dialog.setAttribute('aria-labelledby', titleId);
|
|
30
|
+
else if (name)
|
|
31
|
+
dialog.setAttribute('aria-label', name);
|
|
32
|
+
if (dialogId)
|
|
33
|
+
dialog.id = dialogId;
|
|
34
|
+
backdrop.appendChild(dialog);
|
|
35
|
+
const staticContent = content ? null : renderChildren();
|
|
36
|
+
if (staticContent)
|
|
37
|
+
dialog.appendChild(staticContent.el);
|
|
38
|
+
let activeContent = null;
|
|
39
|
+
let trap = null;
|
|
40
|
+
let onKey = null;
|
|
41
|
+
let onBackdrop = null;
|
|
42
|
+
let mounted = false;
|
|
43
|
+
const mount = () => {
|
|
44
|
+
if (content) {
|
|
45
|
+
activeContent = content();
|
|
46
|
+
dialog.appendChild(activeContent.el);
|
|
47
|
+
}
|
|
48
|
+
onBackdrop = (e) => {
|
|
49
|
+
if (closeOnBackdrop && e.target === backdrop)
|
|
50
|
+
onClose?.();
|
|
51
|
+
};
|
|
52
|
+
backdrop.addEventListener('pointerdown', onBackdrop);
|
|
53
|
+
// Listen on window in capture with stopImmediatePropagation so the modal
|
|
54
|
+
// wins Escape over other document-capture handlers (e.g. the Doctor
|
|
55
|
+
// panel) — stopPropagation alone wouldn't stop same-target listeners.
|
|
56
|
+
onKey = (e) => {
|
|
57
|
+
if (closeOnEscape && e.key === 'Escape') {
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
e.stopImmediatePropagation();
|
|
60
|
+
onClose?.();
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
window.addEventListener('keydown', onKey, true);
|
|
64
|
+
backdrop.hidden = false;
|
|
65
|
+
document.body.appendChild(backdrop);
|
|
66
|
+
trap = new FocusTrap(dialog, {
|
|
67
|
+
initialFocus: initialFocus?.(dialog) ?? undefined,
|
|
68
|
+
escapeDeactivates: false,
|
|
69
|
+
clickOutsideDeactivates: false,
|
|
70
|
+
});
|
|
71
|
+
trap.activate();
|
|
72
|
+
mounted = true;
|
|
73
|
+
};
|
|
74
|
+
const unmount = () => {
|
|
75
|
+
if (onKey) {
|
|
76
|
+
window.removeEventListener('keydown', onKey, true);
|
|
77
|
+
onKey = null;
|
|
78
|
+
}
|
|
79
|
+
trap?.deactivate();
|
|
80
|
+
trap = null;
|
|
81
|
+
if (onBackdrop) {
|
|
82
|
+
backdrop.removeEventListener('pointerdown', onBackdrop);
|
|
83
|
+
onBackdrop = null;
|
|
84
|
+
}
|
|
85
|
+
backdrop.hidden = true;
|
|
86
|
+
backdrop.remove();
|
|
87
|
+
if (activeContent) {
|
|
88
|
+
activeContent.destroy();
|
|
89
|
+
activeContent = null;
|
|
90
|
+
dialog.replaceChildren();
|
|
91
|
+
}
|
|
92
|
+
mounted = false;
|
|
93
|
+
};
|
|
94
|
+
let disposed = false;
|
|
95
|
+
// Defer mount/unmount to a microtask so the content factory's signal reads
|
|
96
|
+
// (e.g. the publish gate) run outside this effect's tracking scope —
|
|
97
|
+
// otherwise the effect would subscribe to them and re-run on unrelated
|
|
98
|
+
// edits. Only open() is tracked here.
|
|
99
|
+
const disposeEffect = effect(() => {
|
|
100
|
+
const isOpen = readReactive(open);
|
|
101
|
+
queueMicrotask(() => {
|
|
102
|
+
if (disposed)
|
|
103
|
+
return;
|
|
104
|
+
if (isOpen && !mounted)
|
|
105
|
+
mount();
|
|
106
|
+
else if (!isOpen && mounted)
|
|
107
|
+
unmount();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
return {
|
|
111
|
+
el: backdrop,
|
|
112
|
+
destroy: () => {
|
|
113
|
+
disposed = true;
|
|
114
|
+
disposeEffect();
|
|
115
|
+
unmount();
|
|
116
|
+
staticContent?.destroy();
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=Modal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Modal.js","sourceRoot":"","sources":["../../../src/organisms/feedback/Modal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.ui-kit.popover",
|
|
4
|
+
"title": "<Popover> Anchored Overlay Component",
|
|
5
|
+
"category": "feature",
|
|
6
|
+
"risk": "high"
|
|
7
|
+
}
|
|
8
|
+
*/
|
|
9
|
+
import { type Reactive } from '../../shared/clickable';
|
|
10
|
+
/** @codexApi {"parent":"pithy.ui-kit.popover","name":"PopoverProps","stability":"stable","signature":"interface PopoverProps"} */
|
|
11
|
+
export interface PopoverProps {
|
|
12
|
+
open: Reactive<boolean>;
|
|
13
|
+
anchorRef: () => HTMLElement | null | undefined;
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
content: () => {
|
|
16
|
+
el: HTMLElement;
|
|
17
|
+
destroy: () => void;
|
|
18
|
+
};
|
|
19
|
+
align?: 'right' | 'center' | 'start';
|
|
20
|
+
gap?: number;
|
|
21
|
+
menuId?: string;
|
|
22
|
+
zIndex?: string;
|
|
23
|
+
backdropClass?: string;
|
|
24
|
+
initialFocus?: (menuEl: HTMLElement) => HTMLElement | null;
|
|
25
|
+
}
|
|
26
|
+
/** @codexApi {"parent":"pithy.ui-kit.popover","name":"Popover","stability":"stable","signature":"(props: PopoverProps) => { destroy: () => void }"} */
|
|
27
|
+
export declare function Popover(props: PopoverProps): {
|
|
28
|
+
destroy: () => void;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=Popover.d.ts.map
|