@nocoo/basalt 2.1.8 → 3.0.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/README.md +2 -0
- package/ai/COMPATIBILITY.md +11 -1
- package/ai/DESIGN.md +342 -0
- package/ai/INTEGRATION.md +239 -152
- package/ai/RECIPES.md +96 -26
- package/ai/USAGE.md +5 -5
- package/ai/registry.json +2883 -275
- package/dist/assets/brand-mark.js.map +1 -1
- package/dist/charts/area.js.map +1 -1
- package/dist/charts/bar.js.map +1 -1
- package/dist/charts/bullet.js.map +1 -1
- package/dist/charts/charts.js.map +1 -1
- package/dist/charts/config.d.ts +11 -11
- package/dist/charts/config.js +4 -4
- package/dist/charts/config.js.map +1 -1
- package/dist/charts/custom-chart.js.map +1 -1
- package/dist/charts/date-navigation.js +10 -10
- package/dist/charts/date-navigation.js.map +1 -1
- package/dist/charts/donut.js +1 -1
- package/dist/charts/donut.js.map +1 -1
- package/dist/charts/frame.d.ts +1 -1
- package/dist/charts/frame.js +4 -4
- package/dist/charts/frame.js.map +1 -1
- package/dist/charts/funnel.js.map +1 -1
- package/dist/charts/gauge.js +5 -5
- package/dist/charts/gauge.js.map +1 -1
- package/dist/charts/grouped-bar.js.map +1 -1
- package/dist/charts/heatmap-calendar.js +11 -11
- package/dist/charts/heatmap-calendar.js.map +1 -1
- package/dist/charts/heatmap-matrix.js +8 -8
- package/dist/charts/heatmap-matrix.js.map +1 -1
- package/dist/charts/item-list.js +1 -1
- package/dist/charts/item-list.js.map +1 -1
- package/dist/charts/legend.js +19 -19
- package/dist/charts/legend.js.map +1 -1
- package/dist/charts/line.js.map +1 -1
- package/dist/charts/palette.js +2 -2
- package/dist/charts/palette.js.map +1 -1
- package/dist/charts/radar.js.map +1 -1
- package/dist/charts/sample.js.map +1 -1
- package/dist/charts/sankey.js.map +1 -1
- package/dist/charts/series.js.map +1 -1
- package/dist/charts/slot-bar.js +2 -2
- package/dist/charts/slot-bar.js.map +1 -1
- package/dist/charts/sparkline.js +38 -23
- package/dist/charts/sparkline.js.map +1 -1
- package/dist/charts/stacked-bar.js.map +1 -1
- package/dist/charts/stat-card.d.ts +2 -2
- package/dist/charts/stat-card.js +61 -58
- package/dist/charts/stat-card.js.map +1 -1
- package/dist/charts/timeline.js +18 -9
- package/dist/charts/timeline.js.map +1 -1
- package/dist/charts/timeseries.js.map +1 -1
- package/dist/charts/tooltip.js +16 -16
- package/dist/charts/tooltip.js.map +1 -1
- package/dist/components/accordion.js +1 -1
- package/dist/components/accordion.js.map +1 -1
- package/dist/components/alert-dialog.js +4 -4
- package/dist/components/alert-dialog.js.map +1 -1
- package/dist/components/app-header.d.ts +5 -1
- package/dist/components/app-header.js +19 -11
- package/dist/components/app-header.js.map +1 -1
- package/dist/components/app-shell.d.ts +4 -1
- package/dist/components/app-shell.js +8 -5
- package/dist/components/app-shell.js.map +1 -1
- package/dist/components/approval-card.d.ts +13 -0
- package/dist/components/approval-card.js +161 -0
- package/dist/components/approval-card.js.map +1 -0
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/avatar.d.ts +12 -0
- package/dist/components/avatar.js +39 -18
- package/dist/components/avatar.js.map +1 -1
- package/dist/components/badge.js +8 -8
- package/dist/components/badge.js.map +1 -1
- package/dist/components/banner.d.ts +2 -2
- package/dist/components/banner.js +9 -8
- package/dist/components/banner.js.map +1 -1
- package/dist/components/basalt-mark.js +1 -1
- package/dist/components/basalt-mark.js.map +1 -1
- package/dist/components/battery-meter.js +5 -5
- package/dist/components/battery-meter.js.map +1 -1
- package/dist/components/breadcrumbs.js +6 -6
- package/dist/components/breadcrumbs.js.map +1 -1
- package/dist/components/button.js +10 -10
- package/dist/components/button.js.map +1 -1
- package/dist/components/chat-bubble.js +4 -3
- package/dist/components/chat-bubble.js.map +1 -1
- package/dist/components/chat-composer.d.ts +21 -3
- package/dist/components/chat-composer.js +126 -60
- package/dist/components/chat-composer.js.map +1 -1
- package/dist/components/chat-header.js +6 -6
- package/dist/components/chat-header.js.map +1 -1
- package/dist/components/chat-inbox.js +34 -30
- package/dist/components/chat-inbox.js.map +1 -1
- package/dist/components/chat-markdown.d.ts +8 -0
- package/dist/components/chat-markdown.js +122 -0
- package/dist/components/chat-markdown.js.map +1 -0
- package/dist/components/chat-message.d.ts +26 -0
- package/dist/components/chat-message.js +145 -0
- package/dist/components/chat-message.js.map +1 -0
- package/dist/components/checkbox.js +11 -11
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/clipboard-text.js +3 -3
- package/dist/components/clipboard-text.js.map +1 -1
- package/dist/components/code.d.ts +22 -20
- package/dist/components/code.js +94 -32
- package/dist/components/code.js.map +1 -1
- package/dist/components/collapsible.js +8 -4
- package/dist/components/collapsible.js.map +1 -1
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/command-palette.js +73 -47
- package/dist/components/command-palette.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +4 -1
- package/dist/components/confirm-dialog.js +20 -18
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/context-cards.d.ts +15 -0
- package/dist/components/context-cards.js +148 -0
- package/dist/components/context-cards.js.map +1 -0
- package/dist/components/context-menu.d.ts +1 -1
- package/dist/components/context-menu.js +18 -14
- package/dist/components/context-menu.js.map +1 -1
- package/dist/components/data-table.d.ts +8 -2
- package/dist/components/data-table.js +161 -106
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.js +13 -13
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/delete-resource.js +1 -1
- package/dist/components/delete-resource.js.map +1 -1
- package/dist/components/description-list.js +3 -3
- package/dist/components/description-list.js.map +1 -1
- package/dist/components/dialog.d.ts +2 -2
- package/dist/components/dialog.js +8 -8
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/diff-table.d.ts +15 -0
- package/dist/components/diff-table.js +146 -0
- package/dist/components/diff-table.js.map +1 -0
- package/dist/components/dock.js +2 -2
- package/dist/components/dock.js.map +1 -1
- package/dist/components/dropdown-menu.js +23 -18
- package/dist/components/dropdown-menu.js.map +1 -1
- package/dist/components/editable-nav-item.js +63 -58
- package/dist/components/editable-nav-item.js.map +1 -1
- package/dist/components/empty.js +6 -6
- package/dist/components/empty.js.map +1 -1
- package/dist/components/fab.js +1 -1
- package/dist/components/fab.js.map +1 -1
- package/dist/components/field.js +3 -3
- package/dist/components/field.js.map +1 -1
- package/dist/components/file-dropzone.js +7 -7
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/filter-bar.js +6 -6
- package/dist/components/filter-bar.js.map +1 -1
- package/dist/components/flow.js +4 -3
- package/dist/components/flow.js.map +1 -1
- package/dist/components/grid.d.ts +3 -1
- package/dist/components/grid.js +15 -8
- package/dist/components/grid.js.map +1 -1
- package/dist/components/hover-card.js +1 -1
- package/dist/components/hover-card.js.map +1 -1
- package/dist/components/icon-picker.d.ts +8 -2
- package/dist/components/icon-picker.js +75 -47
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/inline-editable.js +6 -6
- package/dist/components/inline-editable.js.map +1 -1
- package/dist/components/input-area.js +3 -3
- package/dist/components/input-area.js.map +1 -1
- package/dist/components/input-group.js +5 -5
- package/dist/components/input-group.js.map +1 -1
- package/dist/components/input.js +4 -4
- package/dist/components/input.js.map +1 -1
- package/dist/components/label.js +3 -3
- package/dist/components/label.js.map +1 -1
- package/dist/components/layer-card.d.ts +9 -4
- package/dist/components/layer-card.js +72 -67
- package/dist/components/layer-card.js.map +1 -1
- package/dist/components/link.js.map +1 -1
- package/dist/components/loader.d.ts +16 -10
- package/dist/components/loader.js +46 -53
- package/dist/components/loader.js.map +1 -1
- package/dist/components/loading-screen.js +3 -3
- package/dist/components/loading-screen.js.map +1 -1
- package/dist/components/menu-bar.js +32 -27
- package/dist/components/menu-bar.js.map +1 -1
- package/dist/components/meter.d.ts +5 -5
- package/dist/components/meter.js +25 -12
- package/dist/components/meter.js.map +1 -1
- package/dist/components/multi-select.js +66 -62
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/navigation-menu.d.ts +2 -2
- package/dist/components/navigation-menu.js +22 -8
- package/dist/components/navigation-menu.js.map +1 -1
- package/dist/components/overlay.js +2 -2
- package/dist/components/overlay.js.map +1 -1
- package/dist/components/page-header.d.ts +3 -1
- package/dist/components/page-header.js +12 -12
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/pagination.js +3 -3
- package/dist/components/pagination.js.map +1 -1
- package/dist/components/popover.js +18 -23
- package/dist/components/popover.js.map +1 -1
- package/dist/components/prompt-bar.d.ts +16 -0
- package/dist/components/prompt-bar.js +49 -0
- package/dist/components/prompt-bar.js.map +1 -0
- package/dist/components/radio.js +9 -9
- package/dist/components/radio.js.map +1 -1
- package/dist/components/recommendation-card.d.ts +13 -0
- package/dist/components/recommendation-card.js +123 -0
- package/dist/components/recommendation-card.js.map +1 -0
- package/dist/components/resource-list.js +1 -1
- package/dist/components/resource-list.js.map +1 -1
- package/dist/components/responsive-master-detail.js +7 -7
- package/dist/components/responsive-master-detail.js.map +1 -1
- package/dist/components/scroll-area.js +3 -3
- package/dist/components/scroll-area.js.map +1 -1
- package/dist/components/section-rule.d.ts +5 -3
- package/dist/components/section-rule.js +12 -12
- package/dist/components/section-rule.js.map +1 -1
- package/dist/components/segment-control.js +3 -3
- package/dist/components/segment-control.js.map +1 -1
- package/dist/components/select.js +47 -32
- package/dist/components/select.js.map +1 -1
- package/dist/components/sensitive-input.js +17 -19
- package/dist/components/sensitive-input.js.map +1 -1
- package/dist/components/separator.js.map +1 -1
- package/dist/components/sheet.d.ts +4 -4
- package/dist/components/sheet.js +12 -10
- package/dist/components/sheet.js.map +1 -1
- package/dist/components/sidebar.d.ts +3 -1
- package/dist/components/sidebar.js +150 -138
- package/dist/components/sidebar.js.map +1 -1
- package/dist/components/skeleton-line.d.ts +1 -1
- package/dist/components/skeleton-line.js +2 -2
- package/dist/components/skeleton-line.js.map +1 -1
- package/dist/components/slider.js +2 -2
- package/dist/components/slider.js.map +1 -1
- package/dist/components/stat-strip.js +5 -4
- package/dist/components/stat-strip.js.map +1 -1
- package/dist/components/switch.js +6 -6
- package/dist/components/switch.js.map +1 -1
- package/dist/components/table-of-contents.js +5 -5
- package/dist/components/table-of-contents.js.map +1 -1
- package/dist/components/table-pager.js +2 -2
- package/dist/components/table-pager.js.map +1 -1
- package/dist/components/table.js +4 -4
- package/dist/components/table.js.map +1 -1
- package/dist/components/tabs.js +7 -6
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/tag-badge.d.ts +10 -10
- package/dist/components/tag-badge.js +11 -11
- package/dist/components/tag-badge.js.map +1 -1
- package/dist/components/tag-color-picker.d.ts +8 -1
- package/dist/components/tag-color-picker.js +33 -25
- package/dist/components/tag-color-picker.js.map +1 -1
- package/dist/components/text.js +5 -5
- package/dist/components/text.js.map +1 -1
- package/dist/components/theme-toggle.js +1 -1
- package/dist/components/theme-toggle.js.map +1 -1
- package/dist/components/thinking.d.ts +16 -0
- package/dist/components/thinking.js +85 -0
- package/dist/components/thinking.js.map +1 -0
- package/dist/components/toast.js +25 -20
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toggle-group.js +6 -5
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle.js +6 -6
- package/dist/components/toggle.js.map +1 -1
- package/dist/components/tool-chips.d.ts +12 -0
- package/dist/components/tool-chips.js +138 -0
- package/dist/components/tool-chips.js.map +1 -0
- package/dist/components/toolbar.js +3 -3
- package/dist/components/toolbar.js.map +1 -1
- package/dist/components/tooltip.js +1 -1
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/typeahead-field.js +59 -56
- package/dist/components/typeahead-field.js.map +1 -1
- package/dist/components/upload-queue.js +15 -14
- package/dist/components/upload-queue.js.map +1 -1
- package/dist/models/agent-feedback.d.ts +44 -0
- package/dist/models/agent-feedback.js +28 -0
- package/dist/models/agent-feedback.js.map +1 -0
- package/dist/models/avatar.d.ts +2 -0
- package/dist/models/avatar.js +15 -0
- package/dist/models/avatar.js.map +1 -0
- package/dist/models/code.d.ts +6 -0
- package/dist/models/code.js +24 -0
- package/dist/models/code.js.map +1 -0
- package/dist/models/context-cards.d.ts +13 -0
- package/dist/models/context-cards.js +17 -0
- package/dist/models/context-cards.js.map +1 -0
- package/dist/models/diff-table.d.ts +12 -0
- package/dist/models/diff-table.js +9 -0
- package/dist/models/diff-table.js.map +1 -0
- package/dist/models/recommendation.d.ts +26 -0
- package/dist/models/recommendation.js +23 -0
- package/dist/models/recommendation.js.map +1 -0
- package/dist/providers/accent.js +1 -1
- package/dist/providers/accent.js.map +1 -1
- package/dist/providers/link.js.map +1 -1
- package/dist/providers/theme.js +1 -1
- package/dist/providers/theme.js.map +1 -1
- package/dist/styles/base.css +128 -0
- package/dist/styles/standalone.css +1994 -937
- package/dist/styles/tailwind.css +179 -13
- package/dist/styles/tokens.css +679 -20
- package/dist/utils/cn.js +25 -4
- package/dist/utils/cn.js.map +1 -1
- package/dist/utils/control-surface.d.ts +1 -1
- package/dist/utils/control-surface.js +1 -1
- package/dist/utils/control-surface.js.map +1 -1
- package/dist/utils/navigation.d.ts +3 -0
- package/dist/utils/navigation.js +8 -0
- package/dist/utils/navigation.js.map +1 -0
- package/dist/utils/preference-store.js +1 -1
- package/dist/utils/preference-store.js.map +1 -1
- package/dist/utils/selection-indicator.d.ts +1 -1
- package/dist/utils/selection-indicator.js +49 -72
- package/dist/utils/selection-indicator.js.map +1 -1
- package/dist/utils/use-checkable-group.js.map +1 -1
- package/dist/utils/use-hover-highlight.d.ts +4 -0
- package/dist/utils/use-hover-highlight.js +80 -0
- package/dist/utils/use-hover-highlight.js.map +1 -0
- package/dist/viewmodels/use-approval-card.d.ts +20 -0
- package/dist/viewmodels/use-approval-card.js +83 -0
- package/dist/viewmodels/use-approval-card.js.map +1 -0
- package/dist/viewmodels/use-chat-composer.d.ts +16 -0
- package/dist/viewmodels/use-chat-composer.js +34 -0
- package/dist/viewmodels/use-chat-composer.js.map +1 -0
- package/dist/viewmodels/use-chat-message.d.ts +16 -0
- package/dist/viewmodels/use-chat-message.js +26 -0
- package/dist/viewmodels/use-chat-message.js.map +1 -0
- package/dist/viewmodels/use-code-block.d.ts +8 -0
- package/dist/viewmodels/use-code-block.js +38 -0
- package/dist/viewmodels/use-code-block.js.map +1 -0
- package/dist/viewmodels/use-context-cards.d.ts +17 -0
- package/dist/viewmodels/use-context-cards.js +18 -0
- package/dist/viewmodels/use-context-cards.js.map +1 -0
- package/dist/viewmodels/use-diff-table.d.ts +16 -0
- package/dist/viewmodels/use-diff-table.js +42 -0
- package/dist/viewmodels/use-diff-table.js.map +1 -0
- package/dist/viewmodels/use-loader.d.ts +4 -0
- package/dist/viewmodels/use-loader.js +22 -0
- package/dist/viewmodels/use-loader.js.map +1 -0
- package/dist/viewmodels/use-recommendation-card.d.ts +17 -0
- package/dist/viewmodels/use-recommendation-card.js +41 -0
- package/dist/viewmodels/use-recommendation-card.js.map +1 -0
- package/dist/viewmodels/use-thinking.d.ts +13 -0
- package/dist/viewmodels/use-thinking.js +18 -0
- package/dist/viewmodels/use-thinking.js.map +1 -0
- package/dist/viewmodels/use-tool-chips.d.ts +10 -0
- package/dist/viewmodels/use-tool-chips.js +20 -0
- package/dist/viewmodels/use-tool-chips.js.map +1 -0
- package/package.json +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badge.js","names":[],"sources":["../../src/components/badge.tsx"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nconst badgeVariants = cva(\n\t\"inline-flex items-center gap-
|
|
1
|
+
{"version":3,"file":"badge.js","names":["badgeVariants","cva","Badge","props","cn","BASALT_UI_CLASS","className","dot","children"],"sources":["../../src/components/badge.tsx"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nconst badgeVariants = cva(\n\t\"inline-flex items-center gap-basalt-space-md rounded-basalt-full border basalt-inline font-medium\",\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"border-transparent bg-basalt-primary text-basalt-primary-foreground\",\n\t\t\t\tsecondary: \"border-transparent bg-basalt-secondary text-basalt-foreground\",\n\t\t\t\tdestructive: \"border-transparent bg-basalt-destructive text-basalt-destructive-foreground\",\n\t\t\t\toutline: \"border-basalt-border text-basalt-foreground\",\n\t\t\t\tinfo: \"border-transparent bg-basalt-info-tint text-basalt-info\",\n\t\t\t\tsuccess: \"border-transparent bg-basalt-badge-green text-basalt-badge-green-foreground\",\n\t\t\t\twarning: \"border-transparent bg-basalt-warning-tint text-basalt-warning\",\n\t\t\t\terror: \"border-transparent bg-basalt-danger-tint text-basalt-danger\",\n\t\t\t\tred: \"border-transparent bg-basalt-danger text-basalt-danger-foreground\",\n\t\t\t\torange: \"border-transparent bg-basalt-warning text-basalt-warning-foreground\",\n\t\t\t\tteal: \"border-transparent bg-basalt-badge-teal text-basalt-badge-teal-foreground\",\n\t\t\t\tblue: \"border-transparent bg-basalt-info text-basalt-info-foreground\",\n\t\t\t\tpurple: \"border-transparent bg-basalt-badge-purple text-basalt-badge-purple-foreground\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: { variant: \"default\" },\n\t},\n);\n\nexport interface BadgeProps\n\textends React.HTMLAttributes<HTMLSpanElement>,\n\t\tOmit<VariantProps<typeof badgeVariants>, \"variant\"> {\n\t/**\n\t * Visual style variant for the badge.\n\t *\n\t * Note: Supports standard semantic tones and decorative color tokens.\n\t * Pass null to omit variant styling.\n\t *\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof badgeVariants>[\"variant\"];\n\n\t/**\n\t * Renders a small circular dot indicator before children.\n\t *\n\t * @default false\n\t */\n\tdot?: boolean;\n}\n\nexport function Badge({ className, variant, dot, children, ...props }: BadgeProps) {\n\treturn (\n\t\t<span className={cn(BASALT_UI_CLASS, badgeVariants({ variant }), className)} {...props}>\n\t\t\t{dot ? (\n\t\t\t\t<span className=\"size-basalt-1_5 rounded-basalt-full bg-current\" aria-hidden=\"true\" />\n\t\t\t) : null}\n\t\t\t{children}\n\t\t</span>\n\t);\n}\n"],"mappings":";;;;;;AAKA,IAAMA,IAAgBC,EACrB,qGACA;CACC,UAAU,EACT,SAAS;EACR,SAAS;EACT,WAAW;EACX,aAAa;EACb,SAAS;EACT,MAAM;EACN,SAAS;EACT,SAAS;EACT,OAAO;EACP,KAAK;EACL,QAAQ;EACR,MAAM;EACN,MAAM;EACN,QAAQ;CACT,EACD;CACA,iBAAiB,EAAE,SAAS,UAAU;AACvC,CACD;AAuBA,SAAgBC,EAAM,EAAE,cAAW,YAAS,QAAK,aAAU,GAAGC,KAAqB;CAClF,OACC,kBAAC,QAAD;EAAM,WAAWC,EAAGC,GAAiBL,EAAc,EAAE,WAAQ,CAAC,GAAGM,CAAS;EAAG,GAAIH;EAAjF,UAAA,CACEI,IACA,kBAAC,QAAD;GAAM,WAAU;GAAiD,eAAY;EAAQ,CAAA,IAClF,MACHC,CACI;;AAER"}
|
|
@@ -15,7 +15,7 @@ export interface BannerProps extends Omit<HTMLAttributes<HTMLDivElement>, "title
|
|
|
15
15
|
*/
|
|
16
16
|
variant?: VariantProps<typeof bannerVariants>["variant"];
|
|
17
17
|
/**
|
|
18
|
-
* Sizing preset controlling
|
|
18
|
+
* Sizing preset controlling action placement; shared banner padding stays consistent.
|
|
19
19
|
*
|
|
20
20
|
* Note: Defaults to "base". In compact mode ("sm"), only direct `<Banner.Action>` elements
|
|
21
21
|
* are placed in the trailing slot, while other action content renders inline next to the description.
|
|
@@ -67,7 +67,7 @@ export interface BannerActionProps extends Omit<ButtonProps, "variant" | "size"
|
|
|
67
67
|
/**
|
|
68
68
|
* Sizing preset. When unspecified or null, resolves to "icon" if children are omitted,
|
|
69
69
|
* null, or an empty string, "sm" when parent Banner is compact ("sm"), or "default" otherwise.
|
|
70
|
-
*
|
|
70
|
+
* Icon-only mode uses the shared intrinsic icon action size.
|
|
71
71
|
*/
|
|
72
72
|
size?: ButtonProps["size"];
|
|
73
73
|
/**
|
|
@@ -6,17 +6,17 @@ import { Children as r, createContext as i, isValidElement as a, useContext as o
|
|
|
6
6
|
import { cva as s } from "class-variance-authority";
|
|
7
7
|
import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
8
8
|
//#region src/components/banner.tsx
|
|
9
|
-
var d = s("flex w-full items-start gap-
|
|
9
|
+
var d = s("basalt-banner flex w-full items-start gap-basalt-space-lg rounded-basalt-md", {
|
|
10
10
|
variants: {
|
|
11
11
|
variant: {
|
|
12
12
|
default: "bg-basalt-info-tint text-basalt-info",
|
|
13
13
|
alert: "bg-basalt-warning-tint text-basalt-warning",
|
|
14
14
|
error: "bg-basalt-danger-tint text-basalt-danger",
|
|
15
|
-
secondary: "
|
|
15
|
+
secondary: "text-basalt-foreground"
|
|
16
16
|
},
|
|
17
17
|
size: {
|
|
18
|
-
base: "
|
|
19
|
-
sm: "
|
|
18
|
+
base: "",
|
|
19
|
+
sm: ""
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
defaultVariants: {
|
|
@@ -38,6 +38,7 @@ function m({ className: n, variant: i = "default", size: a = "base", title: o, d
|
|
|
38
38
|
size: y
|
|
39
39
|
},
|
|
40
40
|
children: /* @__PURE__ */ u("div", {
|
|
41
|
+
"data-basalt-surface": v === "secondary" ? "" : void 0,
|
|
41
42
|
className: e(t, d({
|
|
42
43
|
variant: v,
|
|
43
44
|
size: y
|
|
@@ -45,11 +46,11 @@ function m({ className: n, variant: i = "default", size: a = "base", title: o, d
|
|
|
45
46
|
..._,
|
|
46
47
|
children: [
|
|
47
48
|
m ? /* @__PURE__ */ l("span", {
|
|
48
|
-
className: "
|
|
49
|
+
className: "inline-flex h-[1lh] shrink-0 items-center [&_svg]:size-basalt-icon-lg",
|
|
49
50
|
children: m
|
|
50
51
|
}) : null,
|
|
51
52
|
/* @__PURE__ */ u("div", {
|
|
52
|
-
className: "min-w-0 flex-1 space-y-
|
|
53
|
+
className: "min-w-0 flex-1 space-y-basalt-space-xs",
|
|
53
54
|
children: [
|
|
54
55
|
o ? /* @__PURE__ */ l("p", {
|
|
55
56
|
className: "font-medium",
|
|
@@ -63,7 +64,7 @@ function m({ className: n, variant: i = "default", size: a = "base", title: o, d
|
|
|
63
64
|
]
|
|
64
65
|
}),
|
|
65
66
|
w.length > 0 ? /* @__PURE__ */ l("div", {
|
|
66
|
-
className: "flex shrink-0 items-center gap-
|
|
67
|
+
className: "flex shrink-0 items-center gap-basalt-space-lg",
|
|
67
68
|
children: w
|
|
68
69
|
}) : null
|
|
69
70
|
]
|
|
@@ -76,7 +77,7 @@ function h({ className: t, variant: r = "default", size: i, icon: a, children: s
|
|
|
76
77
|
variant: d,
|
|
77
78
|
size: i ?? (p ? "icon" : u.size === "sm" ? "sm" : "default"),
|
|
78
79
|
icon: a,
|
|
79
|
-
className: e(p && "
|
|
80
|
+
className: e(p && "basalt-action-icon", t),
|
|
80
81
|
...c,
|
|
81
82
|
children: s
|
|
82
83
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"banner.js","names":[],"sources":["../../src/components/banner.tsx"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\nimport {\n\tChildren,\n\tcreateContext,\n\ttype HTMLAttributes,\n\tisValidElement,\n\ttype ReactNode,\n\tuseContext,\n} from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button, type ButtonProps } from \"./button\";\n\nconst bannerVariants = cva(\"flex w-full items-start gap-
|
|
1
|
+
{"version":3,"file":"banner.js","names":["_Fragment","Fragment$1","bannerVariants","cva","BannerContext","createContext","isBannerAction","isValidElement","node","BannerAction","BannerRoot","props","resolvedVariant","variant","resolvedSize","size","structured","title","description","nodes","Children","action","ctas","other","trailing","inlineActions","cn","BASALT_UI_CLASS","className","icon","children","banner","useContext","mapped","iconOnly","Button","Banner"],"sources":["../../src/components/banner.tsx"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\nimport {\n\tChildren,\n\tcreateContext,\n\ttype HTMLAttributes,\n\tisValidElement,\n\ttype ReactNode,\n\tuseContext,\n} from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button, type ButtonProps } from \"./button\";\n\nconst bannerVariants = cva(\n\t\"basalt-banner flex w-full items-start gap-basalt-space-lg rounded-basalt-md\",\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"bg-basalt-info-tint text-basalt-info\",\n\t\t\t\talert: \"bg-basalt-warning-tint text-basalt-warning\",\n\t\t\t\terror: \"bg-basalt-danger-tint text-basalt-danger\",\n\t\t\t\tsecondary: \"text-basalt-foreground\",\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tbase: \"\",\n\t\t\t\tsm: \"\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: { variant: \"default\", size: \"base\" },\n\t},\n);\n\ntype BannerVariant = NonNullable<VariantProps<typeof bannerVariants>[\"variant\"]>;\ntype BannerSize = NonNullable<VariantProps<typeof bannerVariants>[\"size\"]>;\n\nconst BannerContext = createContext<{ variant: BannerVariant; size: BannerSize }>({\n\tvariant: \"default\",\n\tsize: \"base\",\n});\n\nexport interface BannerProps\n\textends Omit<HTMLAttributes<HTMLDivElement>, \"title\" | \"children\">,\n\t\tOmit<VariantProps<typeof bannerVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual tone variant of the banner.\n\t *\n\t * Note: Defaults to \"default\" (informational). Passing null falls back to \"default\".\n\t *\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof bannerVariants>[\"variant\"];\n\n\t/**\n\t * Sizing preset controlling action placement; shared banner padding stays consistent.\n\t *\n\t * Note: Defaults to \"base\". In compact mode (\"sm\"), only direct `<Banner.Action>` elements\n\t * are placed in the trailing slot, while other action content renders inline next to the description.\n\t * Passing null falls back to \"base\".\n\t *\n\t * @default \"base\"\n\t */\n\tsize?: VariantProps<typeof bannerVariants>[\"size\"];\n\n\t/**\n\t * Primary heading text.\n\t *\n\t * Note: When present (or when description is present), structured mode is enabled\n\t * and standard children are not rendered.\n\t */\n\ttitle?: string;\n\n\t/**\n\t * Secondary copy rendered below the title.\n\t */\n\tdescription?: ReactNode;\n\n\t/**\n\t * Visual icon rendered before the banner content.\n\t */\n\ticon?: ReactNode;\n\n\t/**\n\t * Trailing or inline call-to-action slot.\n\t * Pass `<Banner.Action>` elements for contextual styling.\n\t * In compact mode (\"sm\"), only direct `<Banner.Action>` elements are placed in the trailing slot,\n\t * while other action content renders inline next to the description.\n\t */\n\taction?: ReactNode;\n\n\t/**\n\t * Unstructured child content rendered only when both title and description are null or undefined.\n\t * When title or description is non-null/non-undefined (including empty string or false),\n\t * structured mode is active and children are ignored.\n\t */\n\tchildren?: HTMLAttributes<HTMLDivElement>[\"children\"];\n}\n\nexport interface BannerActionProps\n\textends Omit<\n\t\tButtonProps,\n\t\t\"variant\" | \"size\" | \"asChild\" | \"type\" | \"loading\" | \"icon\" | \"children\"\n\t> {\n\t/**\n\t * Visual style variant. Preserves \"ghost\" and \"secondary\"; all other values\n\t * are mapped contextually to \"destructive\" (when parent Banner variant is \"error\")\n\t * or \"default\".\n\t *\n\t * Note: Ordinary function component without forwarded ref.\n\t *\n\t * @default \"default\"\n\t */\n\tvariant?: ButtonProps[\"variant\"];\n\n\t/**\n\t * Sizing preset. When unspecified or null, resolves to \"icon\" if children are omitted,\n\t * null, or an empty string, \"sm\" when parent Banner is compact (\"sm\"), or \"default\" otherwise.\n\t * Icon-only mode uses the shared intrinsic icon action size.\n\t */\n\tsize?: ButtonProps[\"size\"];\n\n\t/**\n\t * Pass control to child element slot.\n\t *\n\t * @default false\n\t */\n\tasChild?: ButtonProps[\"asChild\"];\n\n\t/**\n\t * Button type attribute.\n\t *\n\t * @default \"button\"\n\t */\n\ttype?: ButtonProps[\"type\"];\n\n\t/**\n\t * Display loading spinner and disable interactions.\n\t *\n\t * @default false\n\t */\n\tloading?: ButtonProps[\"loading\"];\n\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: ButtonProps[\"icon\"];\n\n\t/**\n\t * Action label content. When null, undefined, or empty string, enables iconOnly sizing mode.\n\t */\n\tchildren?: ButtonProps[\"children\"];\n}\n\nfunction isBannerAction(node: ReactNode): boolean {\n\treturn isValidElement(node) && node.type === BannerAction;\n}\n\nfunction BannerRoot({\n\tclassName,\n\tvariant = \"default\",\n\tsize = \"base\",\n\ttitle,\n\tdescription,\n\ticon,\n\taction,\n\tchildren,\n\t...props\n}: BannerProps) {\n\tconst resolvedVariant = variant ?? \"default\";\n\tconst resolvedSize = size ?? \"base\";\n\tconst structured = title != null || description != null;\n\tconst nodes = Children.toArray(action);\n\tconst ctas = nodes.filter(isBannerAction);\n\tconst other = nodes.filter((node) => !isBannerAction(node));\n\tconst trailing = resolvedSize === \"sm\" ? ctas : [...other, ...ctas];\n\tconst inlineActions = resolvedSize === \"sm\" ? other : [];\n\n\treturn (\n\t\t<BannerContext.Provider value={{ variant: resolvedVariant, size: resolvedSize }}>\n\t\t\t<div\n\t\t\t\tdata-basalt-surface={resolvedVariant === \"secondary\" ? \"\" : undefined}\n\t\t\t\tclassName={cn(\n\t\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\tbannerVariants({ variant: resolvedVariant, size: resolvedSize }),\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{icon ? (\n\t\t\t\t\t<span className=\"inline-flex h-[1lh] shrink-0 items-center [&_svg]:size-basalt-icon-lg\">\n\t\t\t\t\t\t{icon}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t\t<div className=\"min-w-0 flex-1 space-y-basalt-space-xs\">\n\t\t\t\t\t{title ? <p className=\"font-medium\">{title}</p> : null}\n\t\t\t\t\t{description ? (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\tresolvedVariant === \"secondary\" ? \"text-basalt-muted-foreground\" : \"text-current\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{description}\n\t\t\t\t\t\t\t{inlineActions.length > 0 ? <> {inlineActions}</> : null}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : inlineActions.length > 0 ? (\n\t\t\t\t\t\t<div>{inlineActions}</div>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{structured ? null : children}\n\t\t\t\t</div>\n\t\t\t\t{trailing.length > 0 ? (\n\t\t\t\t\t<div className=\"flex shrink-0 items-center gap-basalt-space-lg\">{trailing}</div>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t</BannerContext.Provider>\n\t);\n}\n\nexport function BannerAction({\n\tclassName,\n\tvariant = \"default\",\n\tsize,\n\ticon,\n\tchildren,\n\t...props\n}: BannerActionProps) {\n\tconst banner = useContext(BannerContext);\n\tconst mapped =\n\t\tvariant === \"ghost\"\n\t\t\t? \"ghost\"\n\t\t\t: variant === \"secondary\"\n\t\t\t\t? \"secondary\"\n\t\t\t\t: banner.variant === \"error\"\n\t\t\t\t\t? \"destructive\"\n\t\t\t\t\t: \"default\";\n\tconst iconOnly = children == null || children === \"\";\n\treturn (\n\t\t<Button\n\t\t\tvariant={mapped}\n\t\t\tsize={size ?? (iconOnly ? \"icon\" : banner.size === \"sm\" ? \"sm\" : \"default\")}\n\t\t\ticon={icon}\n\t\t\tclassName={cn(iconOnly && \"basalt-action-icon\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Button>\n\t);\n}\nBannerAction.displayName = \"Banner.Action\";\n\nexport const Banner = Object.assign(BannerRoot, { Action: BannerAction });\n"],"mappings":";;;;;;;;AAaA,IAAME,IAAiBC,EACtB,+EACA;CACC,UAAU;EACT,SAAS;GACR,SAAS;GACT,OAAO;GACP,OAAO;GACP,WAAW;EACZ;EACA,MAAM;GACL,MAAM;GACN,IAAI;EACL;CACD;CACA,iBAAiB;EAAE,SAAS;EAAW,MAAM;CAAO;AACrD,CACD,GAKMC,IAAgBC,EAA4D;CACjF,SAAS;CACT,MAAM;AACP,CAAC;AAkHD,SAASC,EAAe,GAA0B;CACjD,OAAOC,EAAeC,CAAI,KAAKA,EAAK,SAASC;AAC9C;AAEA,SAASC,EAAW,EACnB,cACA,aAAU,WACV,UAAO,QACP,UACA,gBACA,SACA,WACA,aACA,GAAGC,KACY;CACf,IAAMC,IAAkBC,KAAW,WAC7BC,IAAeC,KAAQ,QACvBC,IAAaC,KAAS,QAAQC,KAAe,MAC7CC,IAAQC,EAAS,QAAQC,CAAM,GAC/BC,IAAOH,EAAM,OAAOb,CAAc,GAClCiB,IAAQJ,EAAM,QAAQ,MAAS,CAACb,EAAeE,CAAI,CAAC,GACpDgB,IAAWV,MAAiB,OAAOQ,IAAO,CAAC,GAAGC,GAAO,GAAGD,CAAI,GAC5DG,IAAgBX,MAAiB,OAAOS,IAAQ,CAAC;CAEvD,OACC,kBAACnB,EAAc,UAAf;EAAwB,OAAO;GAAE,SAASQ;GAAiB,MAAME;EAAa;EAC7E,UAAA,kBAAC,OAAD;GACC,uBAAqBF,MAAoB,cAAc,KAAK,KAAA;GAC5D,WAAWc,EACVC,GACAzB,EAAe;IAAE,SAASU;IAAiB,MAAME;GAAa,CAAC,GAC/Dc,CACD;GACA,GAAIjB;GAPL,UAAA;IASEkB,IACA,kBAAC,QAAD;KAAM,WAAU;KACd,UAAAA;IACI,CAAA,IACH;IACJ,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACEZ,IAAQ,kBAAC,KAAD;OAAG,WAAU;OAAe,UAAAA;MAAS,CAAA,IAAI;MACjDC,IACA,kBAAC,OAAD;OACC,WAAWQ,EACVd,MAAoB,cAAc,iCAAiC,cACpE;OAHD,UAAA,CAKEM,GACAO,EAAc,SAAS,IAAI,kBAAAzB,GAAA,EAAA,UAAA,CAAE,KAAEyB,CAAgB,EAAA,CAAA,IAAI,IAChD;MACF,CAAA,IAAAA,EAAc,SAAS,IAC1B,kBAAC,OAAD,EAAA,UAAMA,EAAmB,CAAA,IACtB;MACHT,IAAa,OAAOc;KACjB;;IACJN,EAAS,SAAS,IAClB,kBAAC,OAAD;KAAK,WAAU;KAAkD,UAAAA;IAAc,CAAA,IAC5E;GACA;;CACkB,CAAA;AAE1B;AAEA,SAAgBf,EAAa,EAC5B,cACA,aAAU,WACV,SACA,SACA,aACA,GAAGE,KACkB;CACrB,IAAMoB,IAASC,EAAW5B,CAAa,GACjC6B,IACLpB,MAAY,UACT,UACAA,MAAY,cACX,cACAkB,EAAO,YAAY,UAClB,gBACA,WACAG,IAAWJ,KAAY,QAAQA,MAAa;CAClD,OACC,kBAACK,GAAD;EACC,SAASF;EACT,MAAMlB,MAASmB,IAAW,SAASH,EAAO,SAAS,OAAO,OAAO;EAC3D;EACN,WAAWL,EAAGQ,KAAY,sBAAsBN,CAAS;EACzD,GAAIjB;EAEH;CACM,CAAA;AAEV;AACA,EAAa,cAAc;AAE3B,IAAayB,IAAS,OAAO,OAAO1B,GAAY,EAAE,QAAQD,EAAa,CAAC"}
|
|
@@ -5,7 +5,7 @@ import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
|
5
5
|
//#region src/components/basalt-mark.tsx
|
|
6
6
|
function i({ className: i, ...a }) {
|
|
7
7
|
return /* @__PURE__ */ r("svg", {
|
|
8
|
-
className: e("h-5 w-5", i),
|
|
8
|
+
className: e("h-basalt-5 w-basalt-5", i),
|
|
9
9
|
viewBox: "0 0 128 128",
|
|
10
10
|
role: "img",
|
|
11
11
|
"aria-label": "Basalt",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"basalt-mark.js","names":[],"sources":["../../src/components/basalt-mark.tsx"],"sourcesContent":["import type { SVGAttributes } from \"react\";\nimport { basaltMarkPng } from \"../assets/brand-mark\";\nimport { cn } from \"../utils/cn\";\n\nexport type BasaltMarkProps = Omit<SVGAttributes<SVGSVGElement>, \"className\"> & {\n\t/**\n\t * Additional classes for the mark.\n\t */\n\tclassName?: string;\n};\n\nexport function BasaltMark({ className, ...props }: BasaltMarkProps) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={cn(\"h-5 w-5\", className)}\n\t\t\tviewBox=\"0 0 128 128\"\n\t\t\trole=\"img\"\n\t\t\taria-label=\"Basalt\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<title>Basalt</title>\n\t\t\t<image href={basaltMarkPng} width=\"128\" height=\"128\" />\n\t\t</svg>\n\t);\n}\n"],"mappings":";;;;;AAWA,
|
|
1
|
+
{"version":3,"file":"basalt-mark.js","names":["BasaltMark","props","cn","className","basaltMarkPng"],"sources":["../../src/components/basalt-mark.tsx"],"sourcesContent":["import type { SVGAttributes } from \"react\";\nimport { basaltMarkPng } from \"../assets/brand-mark\";\nimport { cn } from \"../utils/cn\";\n\nexport type BasaltMarkProps = Omit<SVGAttributes<SVGSVGElement>, \"className\"> & {\n\t/**\n\t * Additional classes for the mark.\n\t */\n\tclassName?: string;\n};\n\nexport function BasaltMark({ className, ...props }: BasaltMarkProps) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={cn(\"h-basalt-5 w-basalt-5\", className)}\n\t\t\tviewBox=\"0 0 128 128\"\n\t\t\trole=\"img\"\n\t\t\taria-label=\"Basalt\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<title>Basalt</title>\n\t\t\t<image href={basaltMarkPng} width=\"128\" height=\"128\" />\n\t\t</svg>\n\t);\n}\n"],"mappings":";;;;;AAWA,SAAgBA,EAAW,EAAE,cAAW,GAAGC,KAA0B;CACpE,OACC,kBAAC,OAAD;EACC,WAAWC,EAAG,yBAAyBC,CAAS;EAChD,SAAQ;EACR,MAAK;EACL,cAAW;EACX,GAAIF;EALL,UAAA,CAOC,kBAAC,SAAD,EAAA,UAAO,SAAa,CAAA,GACpB,kBAAC,SAAD;GAAO,MAAMG;GAAe,OAAM;GAAM,QAAO;EAAO,CAAA,CAClD;;AAEP"}
|
|
@@ -6,7 +6,7 @@ import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
|
6
6
|
function i({ value: i, label: a, status: o = "discharging", className: s, ...c }) {
|
|
7
7
|
let l = o !== "offline" && Number.isFinite(i), u = l ? Math.min(100, Math.max(0, i)) : 0, d = u <= 20 ? "bg-basalt-danger" : u <= 50 ? "bg-basalt-warning" : "bg-basalt-primary";
|
|
8
8
|
return /* @__PURE__ */ r("div", {
|
|
9
|
-
className: e(t, "inline-flex items-center gap-
|
|
9
|
+
className: e(t, "inline-flex items-center gap-basalt-space-lg text-basalt-sm tabular-nums", s),
|
|
10
10
|
...c,
|
|
11
11
|
children: [
|
|
12
12
|
l ? /* @__PURE__ */ n("meter", {
|
|
@@ -24,23 +24,23 @@ function i({ value: i, label: a, status: o = "discharging", className: s, ...c }
|
|
|
24
24
|
}),
|
|
25
25
|
/* @__PURE__ */ r("span", {
|
|
26
26
|
"aria-hidden": "true",
|
|
27
|
-
className: "relative inline-flex h-4 w-9 gap-
|
|
27
|
+
className: "relative inline-flex h-basalt-4 w-basalt-9 gap-basalt-space-xs rounded-basalt-sm border border-basalt-muted-foreground/60 p-basalt-space-xs",
|
|
28
28
|
children: [[
|
|
29
29
|
0,
|
|
30
30
|
1,
|
|
31
31
|
2,
|
|
32
32
|
3
|
|
33
33
|
].map((t) => /* @__PURE__ */ n("span", {
|
|
34
|
-
className: "relative flex-1 overflow-hidden rounded-
|
|
34
|
+
className: "relative flex-1 overflow-hidden rounded-basalt-sm bg-basalt-muted",
|
|
35
35
|
children: /* @__PURE__ */ n("span", {
|
|
36
36
|
className: e("absolute inset-y-0 left-0", d),
|
|
37
37
|
style: { width: `${Math.min(100, Math.max(0, u - t * 25) * 4)}%` }
|
|
38
38
|
})
|
|
39
|
-
}, t)), /* @__PURE__ */ n("span", { className: "absolute -right-1 top-1 h-
|
|
39
|
+
}, t)), /* @__PURE__ */ n("span", { className: "absolute -right-basalt-1 top-basalt-1 h-basalt-1_5 w-basalt-0_5 rounded-r-basalt-sm bg-basalt-muted-foreground/60" })]
|
|
40
40
|
}),
|
|
41
41
|
/* @__PURE__ */ n("span", {
|
|
42
42
|
"aria-hidden": "true",
|
|
43
|
-
className: "min-w-9 text-basalt-foreground",
|
|
43
|
+
className: "min-w-basalt-9 text-basalt-foreground",
|
|
44
44
|
children: l ? `${Math.round(u)}%` : "Offline"
|
|
45
45
|
}),
|
|
46
46
|
o === "charging" && l ? /* @__PURE__ */ n("span", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"battery-meter.js","names":[],"sources":["../../src/components/battery-meter.tsx"],"sourcesContent":["import type { HTMLAttributes } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport interface BatteryMeterProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n\t/** Battery charge in percent, clamped to 0–100. Non-finite readings are unavailable. */\n\tvalue: number;\n\t/** Accessible name of the battery. */\n\tlabel: string;\n\t/** Device state, also announced with the value. @default \"discharging\" */\n\tstatus?: \"charging\" | \"discharging\" | \"offline\";\n}\n\nexport function BatteryMeter({\n\tvalue,\n\tlabel,\n\tstatus = \"discharging\",\n\tclassName,\n\t...props\n}: BatteryMeterProps) {\n\tconst available = status !== \"offline\" && Number.isFinite(value);\n\tconst charge = available ? Math.min(100, Math.max(0, value)) : 0;\n\tconst color =\n\t\tcharge <= 20 ? \"bg-basalt-danger\" : charge <= 50 ? \"bg-basalt-warning\" : \"bg-basalt-primary\";\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"inline-flex items-center gap-
|
|
1
|
+
{"version":3,"file":"battery-meter.js","names":["BatteryMeter","props","available","status","value","charge","color","cn","BASALT_UI_CLASS","className","label","segment"],"sources":["../../src/components/battery-meter.tsx"],"sourcesContent":["import type { HTMLAttributes } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport interface BatteryMeterProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n\t/** Battery charge in percent, clamped to 0–100. Non-finite readings are unavailable. */\n\tvalue: number;\n\t/** Accessible name of the battery. */\n\tlabel: string;\n\t/** Device state, also announced with the value. @default \"discharging\" */\n\tstatus?: \"charging\" | \"discharging\" | \"offline\";\n}\n\nexport function BatteryMeter({\n\tvalue,\n\tlabel,\n\tstatus = \"discharging\",\n\tclassName,\n\t...props\n}: BatteryMeterProps) {\n\tconst available = status !== \"offline\" && Number.isFinite(value);\n\tconst charge = available ? Math.min(100, Math.max(0, value)) : 0;\n\tconst color =\n\t\tcharge <= 20 ? \"bg-basalt-danger\" : charge <= 50 ? \"bg-basalt-warning\" : \"bg-basalt-primary\";\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"inline-flex items-center gap-basalt-space-lg text-basalt-sm tabular-nums\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{available ? (\n\t\t\t\t<meter\n\t\t\t\t\tclassName=\"sr-only\"\n\t\t\t\t\tmin={0}\n\t\t\t\t\tmax={100}\n\t\t\t\t\tlow={20}\n\t\t\t\t\thigh={80}\n\t\t\t\t\toptimum={100}\n\t\t\t\t\tvalue={charge}\n\t\t\t\t\taria-label={`${label}, ${status}`}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<span className=\"sr-only\">{label}: unavailable</span>\n\t\t\t)}\n\t\t\t<span\n\t\t\t\taria-hidden=\"true\"\n\t\t\t\tclassName=\"relative inline-flex h-basalt-4 w-basalt-9 gap-basalt-space-xs rounded-basalt-sm border border-basalt-muted-foreground/60 p-basalt-space-xs\"\n\t\t\t>\n\t\t\t\t{[0, 1, 2, 3].map((segment) => (\n\t\t\t\t\t<span\n\t\t\t\t\t\tkey={segment}\n\t\t\t\t\t\tclassName=\"relative flex-1 overflow-hidden rounded-basalt-sm bg-basalt-muted\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclassName={cn(\"absolute inset-y-0 left-0\", color)}\n\t\t\t\t\t\t\tstyle={{ width: `${Math.min(100, Math.max(0, charge - segment * 25) * 4)}%` }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</span>\n\t\t\t\t))}\n\t\t\t\t<span className=\"absolute -right-basalt-1 top-basalt-1 h-basalt-1_5 w-basalt-0_5 rounded-r-basalt-sm bg-basalt-muted-foreground/60\" />\n\t\t\t</span>\n\t\t\t<span aria-hidden=\"true\" className=\"min-w-basalt-9 text-basalt-foreground\">\n\t\t\t\t{available ? `${Math.round(charge)}%` : \"Offline\"}\n\t\t\t</span>\n\t\t\t{status === \"charging\" && available ? (\n\t\t\t\t<span className=\"text-basalt-muted-foreground\">Charging</span>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;AAaA,SAAgBA,EAAa,EAC5B,UACA,UACA,YAAS,eACT,cACA,GAAGC,KACkB;CACrB,IAAMC,IAAYC,MAAW,aAAa,OAAO,SAASC,CAAK,GACzDC,IAASH,IAAY,KAAK,IAAI,KAAK,KAAK,IAAI,GAAGE,CAAK,CAAC,IAAI,GACzDE,IACLD,KAAU,KAAK,qBAAqBA,KAAU,KAAK,sBAAsB;CAC1E,OACC,kBAAC,OAAD;EACC,WAAWE,EACVC,GACA,4EACAC,CACD;EACA,GAAIR;EANL,UAAA;GAQEC,IACA,kBAAC,SAAD;IACC,WAAU;IACV,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,SAAS;IACT,OAAOG;IACP,cAAY,GAAGK,EAAM,IAAIP;GACzB,CAAA,IAED,kBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA,CAA2BO,GAAM,eAAmB;;GAErD,kBAAC,QAAD;IACC,eAAY;IACZ,WAAU;IAFX,UAAA,CAIE;KAAC;KAAG;KAAG;KAAG;IAAC,CAAC,CAAC,KAAK,MAClB,kBAAC,QAAD;KAEC,WAAU;KAEV,UAAA,kBAAC,QAAD;MACC,WAAWH,EAAG,6BAA6BD,CAAK;MAChD,OAAO,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,KAAK,IAAI,GAAGD,IAASM,IAAU,EAAE,IAAI,CAAC,EAAE,GAAG;KAC5E,CAAA;IACI,GAPAA,CAOA,CACN,GACD,kBAAC,QAAD,EAAM,WAAU,oHAAqH,CAAA,CAChI;;GACN,kBAAC,QAAD;IAAM,eAAY;IAAO,WAAU;IACjC,UAAAT,IAAY,GAAG,KAAK,MAAMG,CAAM,EAAE,KAAK;GACnC,CAAA;GACLF,MAAW,cAAcD,IACzB,kBAAC,QAAD;IAAM,WAAU;IAA+B,UAAA;GAAc,CAAA,IAC1D;EACA;;AAEP"}
|
|
@@ -5,24 +5,24 @@ import { Link as n } from "./link.js";
|
|
|
5
5
|
import { ChevronRight as r } from "lucide-react";
|
|
6
6
|
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
7
7
|
//#region src/components/breadcrumbs.tsx
|
|
8
|
-
var o = "text-
|
|
8
|
+
var o = "text-basalt-base font-normal";
|
|
9
9
|
function s({ items: s, className: c }) {
|
|
10
10
|
return /* @__PURE__ */ i("nav", {
|
|
11
11
|
"aria-label": "Breadcrumb",
|
|
12
|
-
className: e(t, "flex items-center gap-
|
|
12
|
+
className: e(t, "flex items-center gap-basalt-space-sm text-basalt-base font-normal text-basalt-muted-foreground", c),
|
|
13
13
|
children: s.map((t, c) => {
|
|
14
14
|
let l = c === s.length - 1 && !t.href, u = t.icon ? /* @__PURE__ */ a("span", {
|
|
15
|
-
className: "inline-flex items-center gap-
|
|
15
|
+
className: "inline-flex items-center gap-basalt-space-sm",
|
|
16
16
|
children: [t.icon, t.label]
|
|
17
17
|
}) : t.label;
|
|
18
18
|
return /* @__PURE__ */ a("span", {
|
|
19
|
-
className: "flex items-center gap-
|
|
19
|
+
className: "flex items-center gap-basalt-space-sm",
|
|
20
20
|
children: [c > 0 ? /* @__PURE__ */ i(r, {
|
|
21
|
-
className: "size-
|
|
21
|
+
className: "size-basalt-icon-sm",
|
|
22
22
|
"aria-hidden": "true"
|
|
23
23
|
}) : null, t.href ? /* @__PURE__ */ i(n, {
|
|
24
24
|
href: t.href,
|
|
25
|
-
className: e(o, "text-basalt-muted-foreground no-underline transition-colors hover:text-basalt-foreground"),
|
|
25
|
+
className: e(o, "text-basalt-muted-foreground no-underline transition-colors basalt-motion hover:text-basalt-foreground"),
|
|
26
26
|
children: u
|
|
27
27
|
}) : /* @__PURE__ */ i("span", {
|
|
28
28
|
"aria-current": l ? "page" : void 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"breadcrumbs.js","names":[],"sources":["../../src/components/breadcrumbs.tsx"],"sourcesContent":["import { ChevronRight } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Link } from \"./link\";\n\nconst crumbTypeClass = \"text-
|
|
1
|
+
{"version":3,"file":"breadcrumbs.js","names":["crumbTypeClass","Breadcrumbs","cn","BASALT_UI_CLASS","className","items","current","index","item","label","ChevronRight","Link"],"sources":["../../src/components/breadcrumbs.tsx"],"sourcesContent":["import { ChevronRight } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Link } from \"./link\";\n\nconst crumbTypeClass = \"text-basalt-base font-normal\";\n\nexport interface BreadcrumbItem {\n\t/**\n\t * Navigation target URL. When omitted, item renders as unlinked text (and only receives aria-current=\"page\" if it is the final item).\n\t */\n\thref?: string;\n\t/**\n\t * Content label rendered inside the breadcrumb segment.\n\t */\n\tlabel: ReactNode;\n\t/**\n\t * Optional leading icon rendered before the label.\n\t */\n\ticon?: ReactNode;\n}\n\nexport interface BreadcrumbsProps {\n\t/**\n\t * List of breadcrumb segments ({ label: ReactNode, href?: string, icon?: ReactNode }[]) in hierarchical order from root to current page.\n\t * Only the final item in the array without an href receives aria-current=\"page\".\n\t * Interactive items render via Link, delegating routing to LinkProvider when configured.\n\t * Component only accepts items and className without native HTML rest attribute forwarding or forwarded ref.\n\t */\n\titems: BreadcrumbItem[];\n\t/**\n\t * Optional class name applied to the outer nav element.\n\t */\n\tclassName?: string;\n}\n\nexport function Breadcrumbs({ items, className }: BreadcrumbsProps) {\n\treturn (\n\t\t<nav\n\t\t\taria-label=\"Breadcrumb\"\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"flex items-center gap-basalt-space-sm text-basalt-base font-normal text-basalt-muted-foreground\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{items.map((item, index) => {\n\t\t\t\tconst current = index === items.length - 1 && !item.href;\n\t\t\t\tconst label = item.icon ? (\n\t\t\t\t\t<span className=\"inline-flex items-center gap-basalt-space-sm\">\n\t\t\t\t\t\t{item.icon}\n\t\t\t\t\t\t{item.label}\n\t\t\t\t\t</span>\n\t\t\t\t) : (\n\t\t\t\t\titem.label\n\t\t\t\t);\n\t\t\t\treturn (\n\t\t\t\t\t<span\n\t\t\t\t\t\tkey={`${String(item.label)}-${index}`}\n\t\t\t\t\t\tclassName=\"flex items-center gap-basalt-space-sm\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{index > 0 ? <ChevronRight className=\"size-basalt-icon-sm\" aria-hidden=\"true\" /> : null}\n\t\t\t\t\t\t{item.href ? (\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\thref={item.href}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\tcrumbTypeClass,\n\t\t\t\t\t\t\t\t\t\"text-basalt-muted-foreground no-underline transition-colors basalt-motion hover:text-basalt-foreground\",\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\taria-current={current ? \"page\" : undefined}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\tcrumbTypeClass,\n\t\t\t\t\t\t\t\t\tcurrent ? \"text-basalt-foreground\" : \"text-basalt-muted-foreground\",\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t);\n\t\t\t})}\n\t\t</nav>\n\t);\n}\n"],"mappings":";;;;;;;AAMA,IAAMA,IAAiB;AA+BvB,SAAgBC,EAAY,EAAE,UAAO,gBAA+B;CACnE,OACC,kBAAC,OAAD;EACC,cAAW;EACX,WAAWC,EACVC,GACA,mGACAC,CACD;EAEC,UAAAC,EAAM,KAAK,GAAM,MAAU;GAC3B,IAAMC,IAAUC,MAAUF,EAAM,SAAS,KAAK,CAACG,EAAK,MAC9CC,IAAQD,EAAK,OAClB,kBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA,CACEA,EAAK,MACLA,EAAK,KACD;GAEN,CAAA,IAAAA,EAAK;GAEN,OACC,kBAAC,QAAD;IAEC,WAAU;IAFX,UAAA,CAIED,IAAQ,IAAI,kBAACG,GAAD;KAAc,WAAU;KAAsB,eAAY;IAAQ,CAAA,IAAI,MAClFF,EAAK,OACL,kBAACG,GAAD;KACC,MAAMH,EAAK;KACX,WAAWN,EACVF,GACA,wGACD;KAEC,UAAAS;IACI,CAAA,IAEN,kBAAC,QAAD;KACC,gBAAcH,IAAU,SAAS,KAAA;KACjC,WAAWJ,EACVF,GACAM,IAAU,2BAA2B,8BACtC;KAEC,UAAAG;IACI,CAAA,CAEF;GAzBA,GAAA,GAAG,OAAOD,EAAK,KAAK,EAAE,GAAGD,GAyBzB;EAER,CAAC;CACG,CAAA;AAEP"}
|
|
@@ -8,21 +8,21 @@ import { cva as a } from "class-variance-authority";
|
|
|
8
8
|
import { Loader2 as o } from "lucide-react";
|
|
9
9
|
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
10
10
|
//#region src/components/button.tsx
|
|
11
|
-
var l = a(`${t} relative inline-flex cursor-pointer items-center justify-center gap-
|
|
11
|
+
var l = a(`${t} relative inline-flex cursor-pointer items-center justify-center gap-basalt-control-gap rounded-basalt-md font-medium wrap-anywhere transition-colors basalt-motion before:absolute before:-inset-basalt-border-width ${n} disabled:pointer-events-none disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0`, {
|
|
12
12
|
variants: {
|
|
13
13
|
variant: {
|
|
14
|
-
default: "bg-basalt-primary text-basalt-primary-foreground hover:bg-basalt-primary
|
|
15
|
-
secondary: "bg-basalt-control text-basalt-foreground hover:bg-basalt-
|
|
16
|
-
destructive: "bg-basalt-destructive text-basalt-destructive-foreground hover:bg-basalt-destructive
|
|
17
|
-
outline: "border border-basalt-border bg-basalt-control hover:bg-basalt-
|
|
18
|
-
ghost: "hover:bg-basalt-
|
|
14
|
+
default: "bg-basalt-primary text-basalt-primary-foreground hover:bg-basalt-primary-hover",
|
|
15
|
+
secondary: "basalt-choice bg-basalt-control text-basalt-foreground hover:bg-basalt-hover",
|
|
16
|
+
destructive: "bg-basalt-destructive text-basalt-destructive-foreground hover:bg-basalt-destructive-hover",
|
|
17
|
+
outline: "basalt-choice border border-basalt-border bg-basalt-control hover:bg-basalt-hover hover:text-basalt-accent-foreground",
|
|
18
|
+
ghost: "basalt-choice hover:bg-basalt-hover hover:text-basalt-accent-foreground",
|
|
19
19
|
link: "text-basalt-primary underline-offset-4 hover:underline"
|
|
20
20
|
},
|
|
21
21
|
size: {
|
|
22
|
-
default: "
|
|
23
|
-
sm: "
|
|
24
|
-
lg: "
|
|
25
|
-
icon: "
|
|
22
|
+
default: "basalt-action [&_svg]:size-basalt-icon",
|
|
23
|
+
sm: "basalt-action basalt-action-sm [&_svg]:size-basalt-icon",
|
|
24
|
+
lg: "basalt-action basalt-action-lg [&_svg]:size-basalt-icon-lg",
|
|
25
|
+
icon: "basalt-action basalt-action-icon shrink-0 [&_svg]:size-basalt-icon"
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
defaultVariants: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.js","names":[],"sources":["../../src/components/button.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Loader2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { FOCUS_RING } from \"./overlay\";\n\n// Keep rounded corners inside the button's rectangular pointer target.\nconst buttonVariants = cva(\n\t`${BASALT_UI_CLASS} relative inline-flex cursor-pointer items-center justify-center gap-2 rounded-basalt-md text-sm font-medium transition-colors before:absolute before:inset-0 ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0`,\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"bg-basalt-primary text-basalt-primary-foreground hover:bg-basalt-primary/90\",\n\t\t\t\tsecondary: \"bg-basalt-control text-basalt-foreground hover:bg-basalt-accent\",\n\t\t\t\tdestructive:\n\t\t\t\t\t\"bg-basalt-destructive text-basalt-destructive-foreground hover:bg-basalt-destructive/90\",\n\t\t\t\toutline:\n\t\t\t\t\t\"border border-basalt-border bg-basalt-control hover:bg-basalt-accent hover:text-basalt-accent-foreground\",\n\t\t\t\tghost: \"hover:bg-basalt-accent hover:text-basalt-accent-foreground\",\n\t\t\t\tlink: \"text-basalt-primary underline-offset-4 hover:underline\",\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: \"h-9 px-4 py-2\",\n\t\t\t\tsm: \"h-8 rounded-basalt-md px-3 text-xs\",\n\t\t\t\tlg: \"h-10 rounded-basalt-md px-6\",\n\t\t\t\ticon: \"h-9 w-9 shrink-0\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: \"default\",\n\t\t\tsize: \"default\",\n\t\t},\n\t},\n);\n\nexport interface ButtonProps\n\textends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"type\">,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Pass control to child element slot.\n\t *\n\t * Note: Child element must forward props and ref in all states. When disabled or loading,\n\t * asChild suppresses click, keyboard activation (Enter/Space), and pointer handlers on both\n\t * child and parent while retaining browser default Tab navigation without trapping focus.\n\t * To preserve single DOM node layout and avoid unexpected child layout shifts, no internal\n\t * spinner is inserted in asChild loading mode; visual disabled state is expressed via aria-disabled.\n\t *\n\t * @default false\n\t */\n\tasChild?: boolean;\n\t/**\n\t * Button type attribute.\n\t * @default \"button\"\n\t */\n\ttype?: React.ButtonHTMLAttributes<HTMLButtonElement>[\"type\"];\n\t/**\n\t * Display loading spinner and disable interactions.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tvariant,\n\t\t\tsize,\n\t\t\tasChild = false,\n\t\t\ttype = \"button\",\n\t\t\tloading = false,\n\t\t\ticon,\n\t\t\tchildren,\n\t\t\tdisabled,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst isDisabled = Boolean(disabled || loading);\n\n\t\tif (asChild) {\n\t\t\tif (isDisabled && React.isValidElement(children)) {\n\t\t\t\tconst childElement = children as React.ReactElement<Record<string, unknown>>;\n\t\t\t\tconst isNativeButton =\n\t\t\t\t\ttypeof childElement.type === \"string\" && childElement.type.toLowerCase() === \"button\";\n\n\t\t\t\tconst blockActivationEvent = (event: React.SyntheticEvent | Event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tif (\n\t\t\t\t\t\t\"stopImmediatePropagation\" in event &&\n\t\t\t\t\t\ttypeof event.stopImmediatePropagation === \"function\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst handleKeyEvent = (event: React.KeyboardEvent) => {\n\t\t\t\t\tif (event.key === \"Enter\" || event.key === \" \" || event.key === \"Spacebar\") {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tif (typeof event.nativeEvent?.stopImmediatePropagation === \"function\") {\n\t\t\t\t\t\tevent.nativeEvent.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst blockedHandlers = {\n\t\t\t\t\tonClick: blockActivationEvent,\n\t\t\t\t\tonClickCapture: blockActivationEvent,\n\t\t\t\t\tonKeyDown: handleKeyEvent,\n\t\t\t\t\tonKeyDownCapture: handleKeyEvent,\n\t\t\t\t\tonKeyUp: handleKeyEvent,\n\t\t\t\t\tonKeyUpCapture: handleKeyEvent,\n\t\t\t\t\tonKeyPress: handleKeyEvent,\n\t\t\t\t\tonKeyPressCapture: handleKeyEvent,\n\t\t\t\t\tonMouseDown: blockActivationEvent,\n\t\t\t\t\tonMouseDownCapture: blockActivationEvent,\n\t\t\t\t\tonMouseUp: blockActivationEvent,\n\t\t\t\t\tonMouseUpCapture: blockActivationEvent,\n\t\t\t\t\tonPointerDown: blockActivationEvent,\n\t\t\t\t\tonPointerDownCapture: blockActivationEvent,\n\t\t\t\t\tonPointerUp: blockActivationEvent,\n\t\t\t\t\tonPointerUpCapture: blockActivationEvent,\n\t\t\t\t\tonAuxClick: blockActivationEvent,\n\t\t\t\t\tonAuxClickCapture: blockActivationEvent,\n\t\t\t\t};\n\n\t\t\t\tconst sanitizedChild = React.cloneElement(childElement, {\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t...(isNativeButton ? { disabled: true } : {}),\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? true : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t});\n\n\t\t\t\tconst slotProps: Record<string, unknown> = {\n\t\t\t\t\t...props,\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? \"true\" : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t};\n\t\t\t\tif (isNativeButton) {\n\t\t\t\t\tslotProps.disabled = true;\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<Slot\n\t\t\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\t{...slotProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t{sanitizedChild}\n\t\t\t\t\t</Slot>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<Slot className={cn(buttonVariants({ variant, size }), className)} ref={ref} {...props}>\n\t\t\t\t\t{children}\n\t\t\t\t</Slot>\n\t\t\t);\n\t\t}\n\n\t\tconst iconNode = loading ? (\n\t\t\t<Loader2 className=\"animate-basalt-spin motion-reduce:animate-none\" aria-hidden=\"true\" />\n\t\t) : (\n\t\t\ticon\n\t\t);\n\t\treturn (\n\t\t\t<button\n\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\tref={ref}\n\t\t\t\ttype={type}\n\t\t\t\tdisabled={isDisabled}\n\t\t\t\taria-busy={loading || undefined}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{iconNode}\n\t\t\t\t{children}\n\t\t\t</button>\n\t\t);\n\t},\n);\nButton.displayName = \"Button\";\n\nexport interface LinkButtonProps\n\textends React.AnchorHTMLAttributes<HTMLAnchorElement>,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const LinkButton = React.forwardRef<HTMLAnchorElement, LinkButtonProps>(\n\t({ className, variant, size, icon, children, ...props }, ref) => (\n\t\t<a ref={ref} className={cn(buttonVariants({ variant, size }), className)} {...props}>\n\t\t\t{icon}\n\t\t\t{children}\n\t\t</a>\n\t),\n);\nLinkButton.displayName = \"LinkButton\";\n\nexport { buttonVariants };\n"],"mappings":";;;;;;;;;;AASA,IAAM,IAAiB,EACtB,GAAG,EAAgB,gKAAgK,EAAW,0KAC9L;CACC,UAAU;EACT,SAAS;GACR,SAAS;GACT,WAAW;GACX,aACC;GACD,SACC;GACD,OAAO;GACP,MAAM;EACP;EACA,MAAM;GACL,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,MAAM;EACP;CACD;CACA,iBAAiB;EAChB,SAAS;EACT,MAAM;CACP;AACD,CACD,GA2Ca,IAAS,EAAM,YAE1B,EACC,cACA,YACA,SACA,aAAU,IACV,UAAO,UACP,aAAU,IACV,SACA,aACA,aACA,GAAG,KAEJ,MACI;CACJ,IAAM,IAAa,GAAQ,KAAY;CAEvC,IAAI,GAAS;EACZ,IAAI,KAAc,EAAM,eAAe,CAAQ,GAAG;GACjD,IAAM,IAAe,GACf,IACL,OAAO,EAAa,QAAS,YAAY,EAAa,KAAK,YAAY,MAAM,UAExE,KAAwB,MAAwC;IAGrE,AAFA,EAAM,eAAe,GACrB,EAAM,gBAAgB,GAErB,8BAA8B,KAC9B,OAAO,EAAM,4BAA6B,cAE1C,EAAM,yBAAyB;GAEjC,GAEM,KAAkB,MAA+B;IAKtD,CAJI,EAAM,QAAQ,WAAW,EAAM,QAAQ,OAAO,EAAM,QAAQ,eAC/D,EAAM,eAAe,GAEtB,EAAM,gBAAgB,GAClB,OAAO,EAAM,aAAa,4BAA6B,cAC1D,EAAM,YAAY,yBAAyB;GAE7C,GAEM,IAAkB;IACvB,SAAS;IACT,gBAAgB;IAChB,WAAW;IACX,kBAAkB;IAClB,SAAS;IACT,gBAAgB;IAChB,YAAY;IACZ,mBAAmB;IACnB,aAAa;IACb,oBAAoB;IACpB,WAAW;IACX,kBAAkB;IAClB,eAAe;IACf,sBAAsB;IACtB,aAAa;IACb,oBAAoB;IACpB,YAAY;IACZ,mBAAmB;GACpB,GAEM,IAAiB,EAAM,aAAa,GAAc;IACvD,GAAG;IACH,GAAI,IAAiB,EAAE,UAAU,GAAK,IAAI,CAAC;IAC3C,iBAAiB;IACjB,aAAa,IAAU,KAAO,KAAA;IAC9B,UAAU;GACX,CAAC,GAEK,IAAqC;IAC1C,GAAG;IACH,GAAG;IACH,iBAAiB;IACjB,aAAa,IAAU,SAAS,KAAA;IAChC,UAAU;GACX;GAKA,OAJI,MACH,EAAU,WAAW,KAIrB,kBAAC,GAAD;IACC,WAAW,EAAG,EAAe;KAAE;KAAS;IAAK,CAAC,GAAG,CAAS;IACrD;IACL,GAAI;IAEH,UAAA;GACI,CAAA;EAER;EAEA,OACC,kBAAC,GAAD;GAAM,WAAW,EAAG,EAAe;IAAE;IAAS;GAAK,CAAC,GAAG,CAAS;GAAQ;GAAK,GAAI;GAC/E;EACI,CAAA;CAER;CAEA,IAAM,IAAW,IAChB,kBAAC,GAAD;EAAS,WAAU;EAAiD,eAAY;CAAQ,CAAA,IAExF;CAED,OACC,kBAAC,UAAD;EACC,WAAW,EAAG,EAAe;GAAE;GAAS;EAAK,CAAC,GAAG,CAAS;EACrD;EACC;EACN,UAAU;EACV,aAAW,KAAW,KAAA;EACtB,GAAI;EANL,UAAA,CAQE,GACA,CACM;;AAEV,CACD;AACA,EAAO,cAAc;AAqBrB,IAAa,IAAa,EAAM,YAC9B,EAAE,cAAW,YAAS,SAAM,SAAM,aAAU,GAAG,KAAS,MACxD,kBAAC,KAAD;CAAQ;CAAK,WAAW,EAAG,EAAe;EAAE;EAAS;CAAK,CAAC,GAAG,CAAS;CAAG,GAAI;CAA9E,UAAA,CACE,GACA,CACC;AAEL,CAAA,CAAA;AACA,EAAW,cAAc"}
|
|
1
|
+
{"version":3,"file":"button.js","names":["React","buttonVariants","cva","BASALT_UI_CLASS","FOCUS_RING","Button","props","isDisabled","disabled","loading","asChild","children","childElement","isNativeButton","blockActivationEvent","event","handleKeyEvent","blockedHandlers","sanitizedChild","slotProps","Slot","cn","className","iconNode","Loader2","icon","LinkButton"],"sources":["../../src/components/button.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Loader2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { FOCUS_RING } from \"./overlay\";\n\n// Keep rounded corners inside the button's rectangular pointer target.\nconst buttonVariants = cva(\n\t`${BASALT_UI_CLASS} relative inline-flex cursor-pointer items-center justify-center gap-basalt-control-gap rounded-basalt-md font-medium wrap-anywhere transition-colors basalt-motion before:absolute before:-inset-basalt-border-width ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0`,\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"bg-basalt-primary text-basalt-primary-foreground hover:bg-basalt-primary-hover\",\n\t\t\t\tsecondary: \"basalt-choice bg-basalt-control text-basalt-foreground hover:bg-basalt-hover\",\n\t\t\t\tdestructive:\n\t\t\t\t\t\"bg-basalt-destructive text-basalt-destructive-foreground hover:bg-basalt-destructive-hover\",\n\t\t\t\toutline:\n\t\t\t\t\t\"basalt-choice border border-basalt-border bg-basalt-control hover:bg-basalt-hover hover:text-basalt-accent-foreground\",\n\t\t\t\tghost: \"basalt-choice hover:bg-basalt-hover hover:text-basalt-accent-foreground\",\n\t\t\t\tlink: \"text-basalt-primary underline-offset-4 hover:underline\",\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: \"basalt-action [&_svg]:size-basalt-icon\",\n\t\t\t\tsm: \"basalt-action basalt-action-sm [&_svg]:size-basalt-icon\",\n\t\t\t\tlg: \"basalt-action basalt-action-lg [&_svg]:size-basalt-icon-lg\",\n\t\t\t\ticon: \"basalt-action basalt-action-icon shrink-0 [&_svg]:size-basalt-icon\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: \"default\",\n\t\t\tsize: \"default\",\n\t\t},\n\t},\n);\n\nexport interface ButtonProps\n\textends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"type\">,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Pass control to child element slot.\n\t *\n\t * Note: Child element must forward props and ref in all states. When disabled or loading,\n\t * asChild suppresses click, keyboard activation (Enter/Space), and pointer handlers on both\n\t * child and parent while retaining browser default Tab navigation without trapping focus.\n\t * To preserve single DOM node layout and avoid unexpected child layout shifts, no internal\n\t * spinner is inserted in asChild loading mode; visual disabled state is expressed via aria-disabled.\n\t *\n\t * @default false\n\t */\n\tasChild?: boolean;\n\t/**\n\t * Button type attribute.\n\t * @default \"button\"\n\t */\n\ttype?: React.ButtonHTMLAttributes<HTMLButtonElement>[\"type\"];\n\t/**\n\t * Display loading spinner and disable interactions.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tvariant,\n\t\t\tsize,\n\t\t\tasChild = false,\n\t\t\ttype = \"button\",\n\t\t\tloading = false,\n\t\t\ticon,\n\t\t\tchildren,\n\t\t\tdisabled,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst isDisabled = Boolean(disabled || loading);\n\n\t\tif (asChild) {\n\t\t\tif (isDisabled && React.isValidElement(children)) {\n\t\t\t\tconst childElement = children as React.ReactElement<Record<string, unknown>>;\n\t\t\t\tconst isNativeButton =\n\t\t\t\t\ttypeof childElement.type === \"string\" && childElement.type.toLowerCase() === \"button\";\n\n\t\t\t\tconst blockActivationEvent = (event: React.SyntheticEvent | Event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tif (\n\t\t\t\t\t\t\"stopImmediatePropagation\" in event &&\n\t\t\t\t\t\ttypeof event.stopImmediatePropagation === \"function\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst handleKeyEvent = (event: React.KeyboardEvent) => {\n\t\t\t\t\tif (event.key === \"Enter\" || event.key === \" \" || event.key === \"Spacebar\") {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tif (typeof event.nativeEvent?.stopImmediatePropagation === \"function\") {\n\t\t\t\t\t\tevent.nativeEvent.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst blockedHandlers = {\n\t\t\t\t\tonClick: blockActivationEvent,\n\t\t\t\t\tonClickCapture: blockActivationEvent,\n\t\t\t\t\tonKeyDown: handleKeyEvent,\n\t\t\t\t\tonKeyDownCapture: handleKeyEvent,\n\t\t\t\t\tonKeyUp: handleKeyEvent,\n\t\t\t\t\tonKeyUpCapture: handleKeyEvent,\n\t\t\t\t\tonKeyPress: handleKeyEvent,\n\t\t\t\t\tonKeyPressCapture: handleKeyEvent,\n\t\t\t\t\tonMouseDown: blockActivationEvent,\n\t\t\t\t\tonMouseDownCapture: blockActivationEvent,\n\t\t\t\t\tonMouseUp: blockActivationEvent,\n\t\t\t\t\tonMouseUpCapture: blockActivationEvent,\n\t\t\t\t\tonPointerDown: blockActivationEvent,\n\t\t\t\t\tonPointerDownCapture: blockActivationEvent,\n\t\t\t\t\tonPointerUp: blockActivationEvent,\n\t\t\t\t\tonPointerUpCapture: blockActivationEvent,\n\t\t\t\t\tonAuxClick: blockActivationEvent,\n\t\t\t\t\tonAuxClickCapture: blockActivationEvent,\n\t\t\t\t};\n\n\t\t\t\tconst sanitizedChild = React.cloneElement(childElement, {\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t...(isNativeButton ? { disabled: true } : {}),\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? true : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t});\n\n\t\t\t\tconst slotProps: Record<string, unknown> = {\n\t\t\t\t\t...props,\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? \"true\" : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t};\n\t\t\t\tif (isNativeButton) {\n\t\t\t\t\tslotProps.disabled = true;\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<Slot\n\t\t\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\t{...slotProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t{sanitizedChild}\n\t\t\t\t\t</Slot>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<Slot className={cn(buttonVariants({ variant, size }), className)} ref={ref} {...props}>\n\t\t\t\t\t{children}\n\t\t\t\t</Slot>\n\t\t\t);\n\t\t}\n\n\t\tconst iconNode = loading ? (\n\t\t\t<Loader2 className=\"animate-basalt-spin motion-reduce:animate-none\" aria-hidden=\"true\" />\n\t\t) : (\n\t\t\ticon\n\t\t);\n\t\treturn (\n\t\t\t<button\n\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\tref={ref}\n\t\t\t\ttype={type}\n\t\t\t\tdisabled={isDisabled}\n\t\t\t\taria-busy={loading || undefined}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{iconNode}\n\t\t\t\t{children}\n\t\t\t</button>\n\t\t);\n\t},\n);\nButton.displayName = \"Button\";\n\nexport interface LinkButtonProps\n\textends React.AnchorHTMLAttributes<HTMLAnchorElement>,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const LinkButton = React.forwardRef<HTMLAnchorElement, LinkButtonProps>(\n\t({ className, variant, size, icon, children, ...props }, ref) => (\n\t\t<a ref={ref} className={cn(buttonVariants({ variant, size }), className)} {...props}>\n\t\t\t{icon}\n\t\t\t{children}\n\t\t</a>\n\t),\n);\nLinkButton.displayName = \"LinkButton\";\n\nexport { buttonVariants };\n"],"mappings":";;;;;;;;;;AASA,IAAMC,IAAiBC,EACtB,GAAGC,EAAgB,wNAAwNC,EAAW,2JACtP;CACC,UAAU;EACT,SAAS;GACR,SAAS;GACT,WAAW;GACX,aACC;GACD,SACC;GACD,OAAO;GACP,MAAM;EACP;EACA,MAAM;GACL,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,MAAM;EACP;CACD;CACA,iBAAiB;EAChB,SAAS;EACT,MAAM;CACP;AACD,CACD,GA2CaC,IAASL,EAAM,YAE1B,EACC,cACA,YACA,SACA,aAAU,IACV,UAAO,UACP,aAAU,IACV,SACA,aACA,aACA,GAAGM,KAEJ,MACI;CACJ,IAAMC,IAAa,GAAQC,KAAYC;CAEvC,IAAIC,GAAS;EACZ,IAAIH,KAAcP,EAAM,eAAeW,CAAQ,GAAG;GACjD,IAAMC,IAAeD,GACfE,IACL,OAAOD,EAAa,QAAS,YAAYA,EAAa,KAAK,YAAY,MAAM,UAExEE,KAAwB,MAAwC;IAGrE,AAFAC,EAAM,eAAe,GACrBA,EAAM,gBAAgB,GAErB,8BAA8BA,KAC9B,OAAOA,EAAM,4BAA6B,cAE1CA,EAAM,yBAAyB;GAEjC,GAEMC,KAAkB,MAA+B;IAKtD,CAJID,EAAM,QAAQ,WAAWA,EAAM,QAAQ,OAAOA,EAAM,QAAQ,eAC/DA,EAAM,eAAe,GAEtBA,EAAM,gBAAgB,GAClB,OAAOA,EAAM,aAAa,4BAA6B,cAC1DA,EAAM,YAAY,yBAAyB;GAE7C,GAEME,IAAkB;IACvB,SAASH;IACT,gBAAgBA;IAChB,WAAWE;IACX,kBAAkBA;IAClB,SAASA;IACT,gBAAgBA;IAChB,YAAYA;IACZ,mBAAmBA;IACnB,aAAaF;IACb,oBAAoBA;IACpB,WAAWA;IACX,kBAAkBA;IAClB,eAAeA;IACf,sBAAsBA;IACtB,aAAaA;IACb,oBAAoBA;IACpB,YAAYA;IACZ,mBAAmBA;GACpB,GAEMI,IAAiBlB,EAAM,aAAaY,GAAc;IACvD,GAAGK;IACH,GAAIJ,IAAiB,EAAE,UAAU,GAAK,IAAI,CAAC;IAC3C,iBAAiB;IACjB,aAAaJ,IAAU,KAAO,KAAA;IAC9B,UAAU;GACX,CAAC,GAEKU,IAAqC;IAC1C,GAAGb;IACH,GAAGW;IACH,iBAAiB;IACjB,aAAaR,IAAU,SAAS,KAAA;IAChC,UAAU;GACX;GAKA,OAJII,MACH,EAAU,WAAW,KAIrB,kBAACO,GAAD;IACC,WAAWC,EAAGpB,EAAe;KAAE;KAAS;IAAK,CAAC,GAAGqB,CAAS;IACrD;IACL,GAAIH;IAEH,UAAAD;GACI,CAAA;EAER;EAEA,OACC,kBAACE,GAAD;GAAM,WAAWC,EAAGpB,EAAe;IAAE;IAAS;GAAK,CAAC,GAAGqB,CAAS;GAAQ;GAAK,GAAIhB;GAC/E;EACI,CAAA;CAER;CAEA,IAAMiB,IAAWd,IAChB,kBAACe,GAAD;EAAS,WAAU;EAAiD,eAAY;CAAQ,CAAA,IAExFC;CAED,OACC,kBAAC,UAAD;EACC,WAAWJ,EAAGpB,EAAe;GAAE;GAAS;EAAK,CAAC,GAAGqB,CAAS;EACrD;EACC;EACN,UAAUf;EACV,aAAWE,KAAW,KAAA;EACtB,GAAIH;EANL,UAAA,CAQEiB,GACAZ,CACM;;AAEV,CACD;AACA,EAAO,cAAc;AAqBrB,IAAae,IAAa1B,EAAM,YAC9B,EAAE,cAAW,YAAS,SAAM,SAAM,aAAU,GAAGM,KAAS,MACxD,kBAAC,KAAD;CAAQ;CAAK,WAAWe,EAAGpB,EAAe;EAAE;EAAS;CAAK,CAAC,GAAGqB,CAAS;CAAG,GAAIhB;CAA9E,UAAA,CACEmB,GACAd,CACC;AAEL,CAAA,CAAA;AACA,EAAW,cAAc"}
|
|
@@ -5,16 +5,17 @@ import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
|
5
5
|
//#region src/components/chat-bubble.tsx
|
|
6
6
|
function i({ variant: i = "assistant", streaming: a = !1, className: o, children: s }) {
|
|
7
7
|
if (i === "system") return /* @__PURE__ */ n("p", {
|
|
8
|
-
className: e(t, "px-
|
|
8
|
+
className: e(t, "px-basalt-space-sm text-center text-basalt-xs text-basalt-muted-foreground", o),
|
|
9
9
|
children: s
|
|
10
10
|
});
|
|
11
11
|
let c = i === "user";
|
|
12
12
|
return /* @__PURE__ */ n("div", {
|
|
13
13
|
className: e(t, "flex w-full", c ? "justify-end" : "justify-start"),
|
|
14
14
|
children: /* @__PURE__ */ r("div", {
|
|
15
|
-
|
|
15
|
+
"data-basalt-surface": c ? void 0 : "",
|
|
16
|
+
className: e("max-w-[92%] px-basalt-panel-x py-basalt-panel-y text-basalt-base leading-[var(--basalt-line-body)] shadow-sm", c ? "rounded-basalt-lg rounded-br-basalt-md bg-basalt-primary text-basalt-primary-foreground" : "rounded-basalt-lg rounded-bl-basalt-md text-basalt-foreground ring-1 ring-basalt-border/50", o),
|
|
16
17
|
children: [s, a ? /* @__PURE__ */ n("span", {
|
|
17
|
-
className: "mt-
|
|
18
|
+
className: "mt-basalt-space-sm inline-block h-basalt-3 w-basalt-1_5 animate-pulse rounded-basalt-sm bg-basalt-primary/70 align-middle motion-reduce:animate-none",
|
|
18
19
|
"aria-hidden": !0
|
|
19
20
|
}) : null]
|
|
20
21
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-bubble.js","names":[],"sources":["../../src/components/chat-bubble.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport type ChatBubbleVariant = \"assistant\" | \"system\" | \"user\";\n\nexport interface ChatBubbleProps {\n\t/**\n\t * Alignment and fill.\n\t * @default \"assistant\"\n\t */\n\tvariant?: ChatBubbleVariant;\n\t/**\n\t * Show a streaming caret after the body.\n\t * @default false\n\t */\n\tstreaming?: boolean;\n\t/**\n\t * Optional class name applied to the message bubble.\n\t * Component only accepts variant, streaming, className, and children without native HTML rest forwarding or forwarded ref.\n\t */\n\tclassName?: string;\n\t/**\n\t * Message content.\n\t */\n\tchildren: ReactNode;\n}\n\nexport function ChatBubble({\n\tvariant = \"assistant\",\n\tstreaming = false,\n\tclassName,\n\tchildren,\n}: ChatBubbleProps) {\n\tif (variant === \"system\") {\n\t\treturn (\n\t\t\t<p\n\t\t\t\tclassName={cn(\n\t\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\t\"px-
|
|
1
|
+
{"version":3,"file":"chat-bubble.js","names":["ChatBubble","variant","cn","BASALT_UI_CLASS","className","user","children","streaming"],"sources":["../../src/components/chat-bubble.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport type ChatBubbleVariant = \"assistant\" | \"system\" | \"user\";\n\nexport interface ChatBubbleProps {\n\t/**\n\t * Alignment and fill.\n\t * @default \"assistant\"\n\t */\n\tvariant?: ChatBubbleVariant;\n\t/**\n\t * Show a streaming caret after the body.\n\t * @default false\n\t */\n\tstreaming?: boolean;\n\t/**\n\t * Optional class name applied to the message bubble.\n\t * Component only accepts variant, streaming, className, and children without native HTML rest forwarding or forwarded ref.\n\t */\n\tclassName?: string;\n\t/**\n\t * Message content.\n\t */\n\tchildren: ReactNode;\n}\n\nexport function ChatBubble({\n\tvariant = \"assistant\",\n\tstreaming = false,\n\tclassName,\n\tchildren,\n}: ChatBubbleProps) {\n\tif (variant === \"system\") {\n\t\treturn (\n\t\t\t<p\n\t\t\t\tclassName={cn(\n\t\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\t\"px-basalt-space-sm text-center text-basalt-xs text-basalt-muted-foreground\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</p>\n\t\t);\n\t}\n\tconst user = variant === \"user\";\n\treturn (\n\t\t<div className={cn(BASALT_UI_CLASS, \"flex w-full\", user ? \"justify-end\" : \"justify-start\")}>\n\t\t\t<div\n\t\t\t\tdata-basalt-surface={user ? undefined : \"\"}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"max-w-[92%] px-basalt-panel-x py-basalt-panel-y text-basalt-base leading-[var(--basalt-line-body)] shadow-sm\",\n\t\t\t\t\tuser\n\t\t\t\t\t\t? \"rounded-basalt-lg rounded-br-basalt-md bg-basalt-primary text-basalt-primary-foreground\"\n\t\t\t\t\t\t: \"rounded-basalt-lg rounded-bl-basalt-md text-basalt-foreground ring-1 ring-basalt-border/50\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t{streaming ? (\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName=\"mt-basalt-space-sm inline-block h-basalt-3 w-basalt-1_5 animate-pulse rounded-basalt-sm bg-basalt-primary/70 align-middle motion-reduce:animate-none\"\n\t\t\t\t\t\taria-hidden\n\t\t\t\t\t/>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;AA4BA,SAAgBA,EAAW,EAC1B,aAAU,aACV,eAAY,IACZ,cACA,eACmB;CACnB,IAAIC,MAAY,UACf,OACC,kBAAC,KAAD;EACC,WAAWC,EACVC,GACA,8EACAC,CACD;EAEC;CACC,CAAA;CAGL,IAAMC,IAAOJ,MAAY;CACzB,OACC,kBAAC,OAAD;EAAK,WAAWC,EAAGC,GAAiB,eAAeE,IAAO,gBAAgB,eAAe;EACxF,UAAA,kBAAC,OAAD;GACC,uBAAqBA,IAAO,KAAA,IAAY;GACxC,WAAWH,EACV,gHACAG,IACG,4FACA,8FACHD,CACD;GARD,UAAA,CAUEE,GACAC,IACA,kBAAC,QAAD;IACC,WAAU;IACV,eAAA;GACA,CAAA,IACE,IACA;;CACD,CAAA;AAEP"}
|
|
@@ -1,4 +1,18 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
1
2
|
export interface ChatComposerProps {
|
|
3
|
+
/** Controlled draft; keep one draft per conversation in the application. */
|
|
4
|
+
value?: string;
|
|
5
|
+
/** Initial draft when uncontrolled. */
|
|
6
|
+
defaultValue?: string;
|
|
7
|
+
onValueChange?: (value: string) => void;
|
|
8
|
+
/** Model, tool and context controls arranged before Send. */
|
|
9
|
+
toolbar?: ReactNode;
|
|
10
|
+
/** Caller-owned attachments; this component never uploads files. */
|
|
11
|
+
attachments?: readonly ChatComposerAttachment[];
|
|
12
|
+
onRemoveAttachment?: (id: string) => void;
|
|
13
|
+
/** Local file selection callback. File validation/upload belong to the application. */
|
|
14
|
+
onFilesSelect?: (files: File[]) => void;
|
|
15
|
+
accept?: string;
|
|
2
16
|
/**
|
|
3
17
|
* Disable the field and send.
|
|
4
18
|
* @default false
|
|
@@ -19,9 +33,9 @@ export interface ChatComposerProps {
|
|
|
19
33
|
*/
|
|
20
34
|
placeholder?: string;
|
|
21
35
|
/**
|
|
22
|
-
* Called with trimmed text
|
|
36
|
+
* Called with trimmed text. Async failure preserves draft and attachments for retry.
|
|
23
37
|
*/
|
|
24
|
-
onSend: (text: string) => void
|
|
38
|
+
onSend: (text: string) => void | Promise<void>;
|
|
25
39
|
/**
|
|
26
40
|
* Called when the stop control is pressed while streaming is active.
|
|
27
41
|
*/
|
|
@@ -42,4 +56,8 @@ export interface ChatComposerProps {
|
|
|
42
56
|
*/
|
|
43
57
|
className?: string;
|
|
44
58
|
}
|
|
45
|
-
export
|
|
59
|
+
export type ChatComposerAttachment = {
|
|
60
|
+
id: string;
|
|
61
|
+
name: string;
|
|
62
|
+
};
|
|
63
|
+
export declare function ChatComposer({ disabled, streaming, label, placeholder, onSend, onCancel, sendLabel, cancelLabel, className, value, defaultValue, onValueChange, toolbar, attachments, onRemoveAttachment, onFilesSelect, accept, }: ChatComposerProps): import("react").JSX.Element;
|