@adea-ai/ui 0.94.0 → 0.95.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -1
- package/dist/NOTICE +10 -0
- package/dist/components/composites/action-button/action-button.d.ts.map +1 -1
- package/dist/components/composites/action-button/action-button.js +2 -0
- package/dist/components/composites/action-button/action-button.js.map +1 -1
- package/dist/components/composites/scene-controls/index.d.ts +3 -0
- package/dist/components/composites/scene-controls/index.d.ts.map +1 -0
- package/dist/components/composites/scene-controls/index.js +2 -0
- package/dist/components/composites/scene-controls/scene-controls.d.ts +41 -0
- package/dist/components/composites/scene-controls/scene-controls.d.ts.map +1 -0
- package/dist/components/composites/scene-controls/scene-controls.js +291 -0
- package/dist/components/composites/scene-controls/scene-controls.js.map +1 -0
- package/dist/components/ui/button/button.d.ts +2 -1
- package/dist/components/ui/button/button.d.ts.map +1 -1
- package/dist/components/ui/button/button.js +9 -3
- package/dist/components/ui/button/button.js.map +1 -1
- package/dist/components/ui/dialog/dialog.d.ts.map +1 -1
- package/dist/components/ui/dialog/dialog.js +5 -1
- package/dist/components/ui/dialog/dialog.js.map +1 -1
- package/dist/components/ui/modal-dialog/modal-dialog.d.ts +6 -0
- package/dist/components/ui/modal-dialog/modal-dialog.d.ts.map +1 -1
- package/dist/components/ui/modal-dialog/modal-dialog.js +4 -0
- package/dist/components/ui/modal-dialog/modal-dialog.js.map +1 -1
- package/dist/components/ui/sheet/sheet.d.ts +8 -1
- package/dist/components/ui/sheet/sheet.d.ts.map +1 -1
- package/dist/components/ui/sheet/sheet.js +43 -19
- package/dist/components/ui/sheet/sheet.js.map +1 -1
- package/dist/components/ui/toggle/toggle.d.ts +1 -1
- package/dist/components/ui/toggle/toggle.d.ts.map +1 -1
- package/dist/components/ui/toggle/toggle.js +3 -1
- package/dist/components/ui/toggle/toggle.js.map +1 -1
- package/dist/components/ui/toggle-group/toggle-group.d.ts.map +1 -1
- package/dist/components/ui/toggle-group/toggle-group.js +20 -7
- package/dist/components/ui/toggle-group/toggle-group.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/lib/tokens.d.ts.map +1 -1
- package/dist/lib/tokens.js +10 -0
- package/dist/lib/tokens.js.map +1 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +2 -0
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/variants.d.ts +5 -2
- package/dist/lib/variants.d.ts.map +1 -1
- package/dist/lib/variants.js +7 -3
- package/dist/lib/variants.js.map +1 -1
- package/dist/lint/index.d.ts.map +1 -1
- package/dist/lint.js +2 -1
- package/dist/lint.js.map +1 -1
- package/dist/r/registry.json +24 -0
- package/dist/r/scene-controls.json +24 -0
- package/dist/r/src/components/composites/action-button/action-button.tsx +2 -0
- package/dist/r/src/components/composites/scene-controls/index.ts +7 -0
- package/dist/r/src/components/composites/scene-controls/scene-controls.tsx +282 -0
- package/dist/r/src/components/ui/button/button.tsx +20 -2
- package/dist/r/src/components/ui/dialog/dialog.tsx +6 -1
- package/dist/r/src/components/ui/modal-dialog/modal-dialog.tsx +20 -0
- package/dist/r/src/components/ui/sheet/sheet.tsx +37 -4
- package/dist/r/src/components/ui/toggle/toggle.tsx +2 -0
- package/dist/r/src/components/ui/toggle-group/toggle-group.tsx +18 -1
- package/dist/r/src/lib/tokens.ts +10 -0
- package/dist/r/src/lib/utils.ts +2 -0
- package/dist/r/src/lib/variants.ts +5 -2
- package/dist/r/src/styles/base.css +29 -9
- package/dist/r/src/styles/theme.css +8 -2
- package/package.json +2 -1
- package/registry.json +24 -0
- package/src/components/composites/action-button/action-button.tsx +2 -0
- package/src/components/composites/scene-controls/index.ts +7 -0
- package/src/components/composites/scene-controls/scene-controls.tsx +282 -0
- package/src/components/ui/button/button.tsx +20 -2
- package/src/components/ui/dialog/dialog.tsx +6 -1
- package/src/components/ui/modal-dialog/modal-dialog.tsx +20 -0
- package/src/components/ui/sheet/sheet.tsx +37 -4
- package/src/components/ui/toggle/toggle.tsx +2 -0
- package/src/components/ui/toggle-group/toggle-group.tsx +18 -1
- package/src/index.ts +1 -0
- package/src/lib/tokens.ts +10 -0
- package/src/lib/utils.ts +2 -0
- package/src/lib/variants.ts +5 -2
- package/src/lint/index.ts +1 -0
- package/src/styles/base.css +29 -9
- package/src/styles/theme.css +8 -2
package/README.md
CHANGED
|
@@ -402,7 +402,8 @@ Square icon controls use the control-height tokens through the Tailwind `--size`
|
|
|
402
402
|
mapping; `--spacing-control-*` remains the separate inline-padding ladder.
|
|
403
403
|
Text controls, icon buttons and toggles share the same height in both densities.
|
|
404
404
|
Dimensions remain rem-based and follow the consumer's root font size. The browser
|
|
405
|
-
geometry lane checks
|
|
405
|
+
geometry lane checks the standard density rungs, heights and padding under both
|
|
406
|
+
themes/densities; the `2xl` touch target remains 48px under compact density.
|
|
406
407
|
|
|
407
408
|
`BusySendButton` translates KiroCrew's split fire/mode-picker composition. Pass
|
|
408
409
|
controlled `mode`, `onModeChange` and `onFire`. `disabled` prevents firing while
|
|
@@ -413,6 +414,47 @@ when the host implements the described keyboard chord. The component adds no
|
|
|
413
414
|
keyboard chord, preference storage, runtime command or queue. Persistence and
|
|
414
415
|
same-session preference synchronization remain application-owned.
|
|
415
416
|
|
|
417
|
+
## Scene controls
|
|
418
|
+
|
|
419
|
+
`SceneControls` composes movement, jump and optional zoom actions for a host
|
|
420
|
+
scene. `onMovementChange(direction, pressed)` and `onJumpChange(pressed)` report
|
|
421
|
+
held state from pointer or keyboard input; zoom callbacks fire once per
|
|
422
|
+
activation. The shared controls capture pointers and release held actions on
|
|
423
|
+
pointer end/cancel, lost capture, window blur and component cleanup. The host
|
|
424
|
+
maps these typed callbacks to its own camera or movement system; the component
|
|
425
|
+
does not synthesize keyboard events or access host globals. Each icon action
|
|
426
|
+
uses the shared tooltip and a `2xl` 48px target that stays that size under
|
|
427
|
+
compact density. Rounded movement and zoom group surfaces use the shared
|
|
428
|
+
scrim treatment, which follows the library's reduced-transparency and fallback
|
|
429
|
+
policy.
|
|
430
|
+
|
|
431
|
+
```tsx
|
|
432
|
+
import { SceneControls } from '@adea-ai/ui/components/composites/scene-controls'
|
|
433
|
+
|
|
434
|
+
;<SceneControls
|
|
435
|
+
onMovementChange={(direction, pressed) => setMovement(direction, pressed)}
|
|
436
|
+
onJumpChange={(pressed) => setJumping(pressed)}
|
|
437
|
+
onZoomIn={zoomIn}
|
|
438
|
+
onZoomOut={zoomOut}
|
|
439
|
+
/>
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Labels default to English and can be supplied through `labels` for a host's
|
|
443
|
+
locale. Hold actions have separate accessible names and explanatory tooltip
|
|
444
|
+
strings so localization can describe the gesture without changing the action
|
|
445
|
+
name. `SceneControls` owns control arrangement and interaction lifecycle;
|
|
446
|
+
the host owns placement, persistence and scene behavior.
|
|
447
|
+
|
|
448
|
+
After building, `bun run check:packed-scene-controls` verifies the installed npm
|
|
449
|
+
archive under both compiled and Solid export conditions. It reuses the
|
|
450
|
+
SceneControls and ActionButton consumer fixtures to check held callback release,
|
|
451
|
+
localized labels, keyboard and pointer cleanup, and the opt-in touch target at
|
|
452
|
+
320px and 200% text. It also checks packed type declarations, license/NOTICE,
|
|
453
|
+
native Node SSR, module separation, and the existing 40 KiB gzip / 32 KiB CSS
|
|
454
|
+
control budgets. The ActionButton fixture with menus and popovers uses the
|
|
455
|
+
existing 38 KiB gzip / 40 KiB CSS overlay budgets. These packed consumer checks
|
|
456
|
+
do not replace product-level native-device acceptance.
|
|
457
|
+
|
|
416
458
|
Kobalte owns the menu and focus lifecycle. Its Tab prevention lacks row cycling,
|
|
417
459
|
so a menu-scoped donor translation cycles enabled rows without a document listener.
|
|
418
460
|
Stories cover before-typing, working,
|
package/dist/NOTICE
CHANGED
|
@@ -451,6 +451,16 @@ excluded. Its distinct `/apps/library` core-app launchpad is also excluded:
|
|
|
451
451
|
this selected unit is the external verified plugin marketplace adapter, while
|
|
452
452
|
Adea's #757 App Library remains a separate core-view and rail-management flow.
|
|
453
453
|
|
|
454
|
+
## Scene controls adapted from Adea
|
|
455
|
+
|
|
456
|
+
`packages/ui/src/components/composites/scene-controls/scene-controls.tsx` adapts
|
|
457
|
+
the d-pad, jump and zoom composition, rounded scrim grouping surfaces and held-input lifecycle from
|
|
458
|
+
`packages/ui/src/components/on-screen-controls.tsx` in the Adea application
|
|
459
|
+
repository (https://github.com/adea-ai/adea), licensed under Apache-2.0.
|
|
460
|
+
The grouping uses the shared `glass-scrim` policy and 48px button variant. The
|
|
461
|
+
component reports typed pressed/released callbacks; it does not copy the host's
|
|
462
|
+
synthetic keyboard events, scene placement or camera behavior.
|
|
463
|
+
|
|
454
464
|
## Windowed tree row composition translated from Terax
|
|
455
465
|
|
|
456
466
|
`packages/ui/src/components/composites/tree/` translates the file-row hierarchy
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-button.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/action-button/action-button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,GAAG,EACR,KAAK,cAAc,EACpB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAI1D;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,cAAc,GAAG,QAAQ,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG;IACpF,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;IACjD,uFAAuF;IACvF,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AA+CD,wBAAgB,YAAY,CAAC,CAAC,SAAS,cAAc,GAAG,QAAQ,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"action-button.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/action-button/action-button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,GAAG,EACR,KAAK,cAAc,EACpB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAI1D;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,cAAc,GAAG,QAAQ,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG;IACpF,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;IACjD,uFAAuF;IACvF,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AA+CD,wBAAgB,YAAY,CAAC,CAAC,SAAS,cAAc,GAAG,QAAQ,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,eAwG5F"}
|
|
@@ -40,6 +40,7 @@ function ActionButton(props) {
|
|
|
40
40
|
"as",
|
|
41
41
|
"variant",
|
|
42
42
|
"size",
|
|
43
|
+
"touchTarget",
|
|
43
44
|
"class",
|
|
44
45
|
"children",
|
|
45
46
|
"disabled",
|
|
@@ -61,6 +62,7 @@ function ActionButton(props) {
|
|
|
61
62
|
...rest,
|
|
62
63
|
variant: local.variant,
|
|
63
64
|
size: local.size,
|
|
65
|
+
touchTarget: local.touchTarget,
|
|
64
66
|
class: [local.class, local.tooltip && disabled() && "aria-disabled:pointer-events-auto"].filter(Boolean).join(" "),
|
|
65
67
|
disabled: disabled() && !local.tooltip,
|
|
66
68
|
"aria-disabled": disabled() ? true : rest["aria-disabled"],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-button.js","names":["Show","createSignal","splitProps","ComponentProps","JSX","ValidComponent","Button","ButtonProps","Spinner","Tooltip","TooltipContent","TooltipTrigger","ActionButtonProps","T","tooltip","tooltipSide","busy","busyLabel","invokeHandler","handler","event","Event","Array","isArray","callback","data","chainedHandler","before","guardedClick","disabled","onActivate","MouseEvent","preventDefault","stopImmediatePropagation","ButtonTargetProps","Omit","actionAs","ButtonTarget","props","local","rest","PolymorphicButton","targetProps","Element","_$createComponent","_$mergeProps","as","ActionButton","busyStatus","tooltipOpen","setTooltipOpen","tooltipSuppression","setTooltipSuppression","onClickCapture","buttonProps","PolymorphicButtonTarget","variant","size","class","filter","Boolean","join","tabIndex","undefined","role","href","onClick","detail","onPointerLeave","onBlur","Record","contents","when","children","label","_$memo","fallback","open","onOpenChange","side","_el$","_tmpl$","_$insert","_$createComponent","PolymorphicButton","_$mergeProps","_$memo"],"sources":["../../../../src/components/composites/action-button/action-button.tsx"],"sourcesContent":["import {\n Show,\n createSignal,\n splitProps,\n type ComponentProps,\n type JSX,\n type ValidComponent,\n} from 'solid-js'\nimport { Button, type ButtonProps } from '../../ui/button'\nimport { Spinner } from '../../ui/spinner'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../../ui/tooltip'\n\n/**\n * ActionButton.\n *\n * A Button with optional explanatory tooltip and busy feedback. Use it for a\n * simple action that needs these states; actions with product-specific rules\n * should compose Button directly.\n *\n * The tooltip trigger renders the polymorphic Button itself. A disabled native\n * control cannot receive pointer or keyboard events. When a tooltip is set,\n * disabled actions therefore use focusable `aria-disabled` semantics and guard\n * activation; without a tooltip, native buttons retain native disabling.\n * Custom polymorphic components must forward aria, event, and href props for\n * these guarantees to apply.\n */\nexport type ActionButtonProps<T extends ValidComponent = 'button'> = ButtonProps<T> & {\n /** A short explanation, also shown on keyboard focus. The Button still needs its own name. */\n tooltip?: string\n tooltipSide?: 'top' | 'right' | 'bottom' | 'left'\n /** Disables the action and announces the busy label through a polite status region. */\n busy?: boolean\n /** The activity announced while busy. The Button's accessible name stays unchanged. */\n busyLabel?: string\n}\n\nfunction invokeHandler(handler: unknown, event: Event) {\n if (Array.isArray(handler)) {\n const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]\n callback(data, event)\n } else if (typeof handler === 'function') {\n const callback = handler as (event: Event) => void\n callback(event)\n }\n}\n\nfunction chainedHandler(handler: unknown, before: (event: Event) => void) {\n return (event: Event) => {\n before(event)\n invokeHandler(handler, event)\n }\n}\n\nfunction guardedClick(\n handler: unknown,\n disabled: () => boolean,\n onActivate: (event: MouseEvent) => void = () => {}\n) {\n return (event: MouseEvent) => {\n if (disabled()) {\n event.preventDefault()\n event.stopImmediatePropagation()\n return\n }\n\n onActivate(event)\n invokeHandler(handler, event)\n }\n}\n\ntype ButtonTargetProps<T extends ValidComponent = 'button'> = Omit<ButtonProps<T>, 'as'> & {\n actionAs?: T\n}\n\n/** Adapter keeps TooltipTrigger's `as` separate from Button's polymorphic `as`. */\nfunction ButtonTarget<T extends ValidComponent = 'button'>(props: ButtonTargetProps<T>) {\n const [local, rest] = splitProps(props as ButtonTargetProps, ['actionAs'])\n const PolymorphicButton = Button as (targetProps: ButtonProps<T>) => JSX.Element\n return <PolymorphicButton as={(local.actionAs ?? 'button') as T} {...(rest as ButtonProps<T>)} />\n}\n\nexport function ActionButton<T extends ValidComponent = 'button'>(props: ActionButtonProps<T>) {\n const [local, rest] = splitProps(props as ActionButtonProps, [\n 'as',\n 'variant',\n 'size',\n 'class',\n 'children',\n 'disabled',\n 'aria-busy',\n 'tooltip',\n 'tooltipSide',\n 'busy',\n 'busyLabel',\n ])\n const busy = () => local.busy ?? false\n const disabled = () => busy() || !!local.disabled\n const busyStatus = () => local.busyLabel ?? 'Working'\n const [tooltipOpen, setTooltipOpen] = createSignal(false)\n const [tooltipSuppression, setTooltipSuppression] = createSignal<'pointer' | 'focus' | null>(null)\n const onClickCapture = (rest as { onClickCapture?: unknown }).onClickCapture\n const PolymorphicButton = Button as (buttonProps: ButtonProps<T>) => JSX.Element\n const PolymorphicButtonTarget = ButtonTarget as (targetProps: ButtonTargetProps<T>) => JSX.Element\n\n const buttonProps = () => ({\n ...rest,\n variant: local.variant,\n size: local.size,\n class: [local.class, local.tooltip && disabled() && 'aria-disabled:pointer-events-auto']\n .filter(Boolean)\n .join(' '),\n disabled: disabled() && !local.tooltip,\n 'aria-disabled': disabled() ? true : rest['aria-disabled'],\n // Make tooltip-bearing native controls explicit tab stops in WebKit configurations that\n // otherwise skip implicit button stops. A caller's tabIndex remains authoritative.\n tabIndex:\n rest.tabIndex ??\n (local.as === 'a' && disabled() ? (local.tooltip ? 0 : -1) : local.tooltip ? 0 : undefined),\n role: local.as === 'a' && disabled() ? 'link' : rest.role,\n href: local.as === 'a' && disabled() ? undefined : (rest as { href?: string }).href,\n 'aria-busy': busy() || local['aria-busy'],\n onClick: guardedClick(rest.onClick, disabled, (event) => {\n if (!local.tooltip) return\n setTooltipSuppression(event.detail > 0 ? 'pointer' : 'focus')\n setTooltipOpen(false)\n }),\n onPointerLeave: chainedHandler(rest.onPointerLeave, () => {\n if (tooltipSuppression() === 'pointer') setTooltipSuppression(null)\n }),\n onBlur: chainedHandler(rest.onBlur, () => {\n if (tooltipSuppression() === 'focus') setTooltipSuppression(null)\n }),\n onClickCapture: onClickCapture ? guardedClick(onClickCapture, disabled) : undefined,\n 'on:click': guardedClick((rest as Record<string, unknown>)['on:click'], disabled),\n 'oncapture:click': guardedClick((rest as Record<string, unknown>)['oncapture:click'], disabled),\n })\n\n const contents = () => (\n <>\n <Show when={busy()}>\n <Spinner size=\"sm\" label={false} aria-hidden=\"true\" data-icon=\"inline-start\" />\n </Show>\n {local.children}\n </>\n )\n\n return (\n <>\n <Show\n when={local.tooltip}\n fallback={\n <PolymorphicButton\n as={(local.as ?? 'button') as T}\n {...(buttonProps() as unknown as ButtonProps<T>)}\n >\n {contents()}\n </PolymorphicButton>\n }\n >\n <Tooltip\n open={tooltipOpen()}\n onOpenChange={(open) => {\n if (open && tooltipSuppression()) return\n setTooltipOpen(open)\n }}\n >\n <TooltipTrigger\n as={PolymorphicButtonTarget}\n {...(buttonProps() as unknown as ComponentProps<typeof PolymorphicButtonTarget>)}\n actionAs={(local.as ?? 'button') as T}\n >\n {contents()}\n </TooltipTrigger>\n <TooltipContent side={local.tooltipSide}>{local.tooltip}</TooltipContent>\n </Tooltip>\n </Show>\n <Show when={busy()}>\n <span role=\"status\" aria-live=\"polite\" class=\"visually-hidden\">\n {busyStatus()}\n </span>\n </Show>\n </>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"action-button.js","names":["Show","createSignal","splitProps","ComponentProps","JSX","ValidComponent","Button","ButtonProps","Spinner","Tooltip","TooltipContent","TooltipTrigger","ActionButtonProps","T","tooltip","tooltipSide","busy","busyLabel","invokeHandler","handler","event","Event","Array","isArray","callback","data","chainedHandler","before","guardedClick","disabled","onActivate","MouseEvent","preventDefault","stopImmediatePropagation","ButtonTargetProps","Omit","actionAs","ButtonTarget","props","local","rest","PolymorphicButton","targetProps","Element","_$createComponent","_$mergeProps","as","ActionButton","busyStatus","tooltipOpen","setTooltipOpen","tooltipSuppression","setTooltipSuppression","onClickCapture","buttonProps","PolymorphicButtonTarget","variant","size","touchTarget","class","filter","Boolean","join","tabIndex","undefined","role","href","onClick","detail","onPointerLeave","onBlur","Record","contents","when","children","label","_$memo","fallback","open","onOpenChange","side","_el$","_tmpl$","_$insert","_$createComponent","PolymorphicButton","_$mergeProps","_$memo"],"sources":["../../../../src/components/composites/action-button/action-button.tsx"],"sourcesContent":["import {\n Show,\n createSignal,\n splitProps,\n type ComponentProps,\n type JSX,\n type ValidComponent,\n} from 'solid-js'\nimport { Button, type ButtonProps } from '../../ui/button'\nimport { Spinner } from '../../ui/spinner'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../../ui/tooltip'\n\n/**\n * ActionButton.\n *\n * A Button with optional explanatory tooltip and busy feedback. Use it for a\n * simple action that needs these states; actions with product-specific rules\n * should compose Button directly.\n *\n * The tooltip trigger renders the polymorphic Button itself. A disabled native\n * control cannot receive pointer or keyboard events. When a tooltip is set,\n * disabled actions therefore use focusable `aria-disabled` semantics and guard\n * activation; without a tooltip, native buttons retain native disabling.\n * Custom polymorphic components must forward aria, event, and href props for\n * these guarantees to apply.\n */\nexport type ActionButtonProps<T extends ValidComponent = 'button'> = ButtonProps<T> & {\n /** A short explanation, also shown on keyboard focus. The Button still needs its own name. */\n tooltip?: string\n tooltipSide?: 'top' | 'right' | 'bottom' | 'left'\n /** Disables the action and announces the busy label through a polite status region. */\n busy?: boolean\n /** The activity announced while busy. The Button's accessible name stays unchanged. */\n busyLabel?: string\n}\n\nfunction invokeHandler(handler: unknown, event: Event) {\n if (Array.isArray(handler)) {\n const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]\n callback(data, event)\n } else if (typeof handler === 'function') {\n const callback = handler as (event: Event) => void\n callback(event)\n }\n}\n\nfunction chainedHandler(handler: unknown, before: (event: Event) => void) {\n return (event: Event) => {\n before(event)\n invokeHandler(handler, event)\n }\n}\n\nfunction guardedClick(\n handler: unknown,\n disabled: () => boolean,\n onActivate: (event: MouseEvent) => void = () => {}\n) {\n return (event: MouseEvent) => {\n if (disabled()) {\n event.preventDefault()\n event.stopImmediatePropagation()\n return\n }\n\n onActivate(event)\n invokeHandler(handler, event)\n }\n}\n\ntype ButtonTargetProps<T extends ValidComponent = 'button'> = Omit<ButtonProps<T>, 'as'> & {\n actionAs?: T\n}\n\n/** Adapter keeps TooltipTrigger's `as` separate from Button's polymorphic `as`. */\nfunction ButtonTarget<T extends ValidComponent = 'button'>(props: ButtonTargetProps<T>) {\n const [local, rest] = splitProps(props as ButtonTargetProps, ['actionAs'])\n const PolymorphicButton = Button as (targetProps: ButtonProps<T>) => JSX.Element\n return <PolymorphicButton as={(local.actionAs ?? 'button') as T} {...(rest as ButtonProps<T>)} />\n}\n\nexport function ActionButton<T extends ValidComponent = 'button'>(props: ActionButtonProps<T>) {\n const [local, rest] = splitProps(props as ActionButtonProps, [\n 'as',\n 'variant',\n 'size',\n 'touchTarget',\n 'class',\n 'children',\n 'disabled',\n 'aria-busy',\n 'tooltip',\n 'tooltipSide',\n 'busy',\n 'busyLabel',\n ])\n const busy = () => local.busy ?? false\n const disabled = () => busy() || !!local.disabled\n const busyStatus = () => local.busyLabel ?? 'Working'\n const [tooltipOpen, setTooltipOpen] = createSignal(false)\n const [tooltipSuppression, setTooltipSuppression] = createSignal<'pointer' | 'focus' | null>(null)\n const onClickCapture = (rest as { onClickCapture?: unknown }).onClickCapture\n const PolymorphicButton = Button as (buttonProps: ButtonProps<T>) => JSX.Element\n const PolymorphicButtonTarget = ButtonTarget as (targetProps: ButtonTargetProps<T>) => JSX.Element\n\n const buttonProps = () => ({\n ...rest,\n variant: local.variant,\n size: local.size,\n touchTarget: local.touchTarget,\n class: [local.class, local.tooltip && disabled() && 'aria-disabled:pointer-events-auto']\n .filter(Boolean)\n .join(' '),\n disabled: disabled() && !local.tooltip,\n 'aria-disabled': disabled() ? true : rest['aria-disabled'],\n // Make tooltip-bearing native controls explicit tab stops in WebKit configurations that\n // otherwise skip implicit button stops. A caller's tabIndex remains authoritative.\n tabIndex:\n rest.tabIndex ??\n (local.as === 'a' && disabled() ? (local.tooltip ? 0 : -1) : local.tooltip ? 0 : undefined),\n role: local.as === 'a' && disabled() ? 'link' : rest.role,\n href: local.as === 'a' && disabled() ? undefined : (rest as { href?: string }).href,\n 'aria-busy': busy() || local['aria-busy'],\n onClick: guardedClick(rest.onClick, disabled, (event) => {\n if (!local.tooltip) return\n setTooltipSuppression(event.detail > 0 ? 'pointer' : 'focus')\n setTooltipOpen(false)\n }),\n onPointerLeave: chainedHandler(rest.onPointerLeave, () => {\n if (tooltipSuppression() === 'pointer') setTooltipSuppression(null)\n }),\n onBlur: chainedHandler(rest.onBlur, () => {\n if (tooltipSuppression() === 'focus') setTooltipSuppression(null)\n }),\n onClickCapture: onClickCapture ? guardedClick(onClickCapture, disabled) : undefined,\n 'on:click': guardedClick((rest as Record<string, unknown>)['on:click'], disabled),\n 'oncapture:click': guardedClick((rest as Record<string, unknown>)['oncapture:click'], disabled),\n })\n\n const contents = () => (\n <>\n <Show when={busy()}>\n <Spinner size=\"sm\" label={false} aria-hidden=\"true\" data-icon=\"inline-start\" />\n </Show>\n {local.children}\n </>\n )\n\n return (\n <>\n <Show\n when={local.tooltip}\n fallback={\n <PolymorphicButton\n as={(local.as ?? 'button') as T}\n {...(buttonProps() as unknown as ButtonProps<T>)}\n >\n {contents()}\n </PolymorphicButton>\n }\n >\n <Tooltip\n open={tooltipOpen()}\n onOpenChange={(open) => {\n if (open && tooltipSuppression()) return\n setTooltipOpen(open)\n }}\n >\n <TooltipTrigger\n as={PolymorphicButtonTarget}\n {...(buttonProps() as unknown as ComponentProps<typeof PolymorphicButtonTarget>)}\n actionAs={(local.as ?? 'button') as T}\n >\n {contents()}\n </TooltipTrigger>\n <TooltipContent side={local.tooltipSide}>{local.tooltip}</TooltipContent>\n </Tooltip>\n </Show>\n <Show when={busy()}>\n <span role=\"status\" aria-live=\"polite\" class=\"visually-hidden\">\n {busyStatus()}\n </span>\n </Show>\n </>\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/scene-controls/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,GAC5B,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type JSX } from 'solid-js';
|
|
2
|
+
/** A host-neutral direction reported while a movement control is held. */
|
|
3
|
+
export type SceneMovementDirection = 'forward' | 'left' | 'backward' | 'right';
|
|
4
|
+
/** Accessible names and tooltip text for the shared scene controls. */
|
|
5
|
+
export type SceneControlLabels = {
|
|
6
|
+
movementGroup: string;
|
|
7
|
+
forward: string;
|
|
8
|
+
forwardTooltip: string;
|
|
9
|
+
left: string;
|
|
10
|
+
leftTooltip: string;
|
|
11
|
+
backward: string;
|
|
12
|
+
backwardTooltip: string;
|
|
13
|
+
right: string;
|
|
14
|
+
rightTooltip: string;
|
|
15
|
+
jump: string;
|
|
16
|
+
jumpTooltip: string;
|
|
17
|
+
zoomGroup: string;
|
|
18
|
+
zoomOut: string;
|
|
19
|
+
zoomIn: string;
|
|
20
|
+
};
|
|
21
|
+
export type SceneControlsProps = {
|
|
22
|
+
/** Called on the transition into and out of each held movement direction. */
|
|
23
|
+
onMovementChange?: (direction: SceneMovementDirection, pressed: boolean) => void;
|
|
24
|
+
/** Called when the jump action becomes pressed or released. */
|
|
25
|
+
onJumpChange?: (pressed: boolean) => void;
|
|
26
|
+
/** Called once when zoom in is activated. */
|
|
27
|
+
onZoomIn?: () => void;
|
|
28
|
+
/** Called once when zoom out is activated. */
|
|
29
|
+
onZoomOut?: () => void;
|
|
30
|
+
/** Override the default English accessible names and tooltip copy. */
|
|
31
|
+
labels?: Partial<SceneControlLabels>;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Shared movement, jump and zoom controls for a host-rendered scene.
|
|
35
|
+
*
|
|
36
|
+
* Movement and jump callbacks receive pressed/released state from pointer and
|
|
37
|
+
* keyboard input. Zoom callbacks fire on activation. The host owns positioning,
|
|
38
|
+
* scene state and camera behavior.
|
|
39
|
+
*/
|
|
40
|
+
export declare function SceneControls(props: SceneControlsProps): JSX.Element;
|
|
41
|
+
//# sourceMappingURL=scene-controls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-controls.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/scene-controls/scene-controls.tsx"],"names":[],"mappings":"AACA,OAAO,EAAiC,KAAK,GAAG,EAAE,MAAM,UAAU,CAAA;AAGlE,0EAA0E;AAC1E,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAA;AAE9E,uEAAuE;AACvE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAsBD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAChF,+DAA+D;IAC/D,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IACzC,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAA;CACrC,CAAA;AAmHD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,eAuGtD"}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { ActionButton } from "../action-button/action-button.js";
|
|
2
|
+
import { createComponent, effect, insert, setAttribute, template } from "solid-js/web";
|
|
3
|
+
import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, ZoomIn, ZoomOut } from "lucide-solid";
|
|
4
|
+
import { Show, createSignal, onCleanup } from "solid-js";
|
|
5
|
+
//#region src/components/composites/scene-controls/scene-controls.tsx
|
|
6
|
+
var _tmpl$ = /*#__PURE__*/ template(`<div role=group class="glass-scrim grid min-w-0 max-w-full grid-cols-3 gap-1.5 rounded-3xl p-2"><span aria-hidden=true></span><span aria-hidden=true>`);
|
|
7
|
+
var _tmpl$2 = /*#__PURE__*/ template(`<div role=group class="glass-scrim flex min-w-0 max-w-full flex-wrap gap-1.5 rounded-2xl p-1.5">`);
|
|
8
|
+
var _tmpl$3 = /*#__PURE__*/ template(`<div class="flex min-w-0 max-w-full flex-wrap items-end gap-3"><div class="ml-auto flex min-w-0 max-w-full flex-col items-end gap-2">`);
|
|
9
|
+
var DEFAULT_LABELS = {
|
|
10
|
+
movementGroup: "Scene movement controls",
|
|
11
|
+
forward: "Move forward",
|
|
12
|
+
forwardTooltip: "Hold to move forward",
|
|
13
|
+
left: "Move left",
|
|
14
|
+
leftTooltip: "Hold to move left",
|
|
15
|
+
backward: "Move backward",
|
|
16
|
+
backwardTooltip: "Hold to move backward",
|
|
17
|
+
right: "Move right",
|
|
18
|
+
rightTooltip: "Hold to move right",
|
|
19
|
+
jump: "Jump",
|
|
20
|
+
jumpTooltip: "Hold to jump",
|
|
21
|
+
zoomGroup: "Camera zoom",
|
|
22
|
+
zoomOut: "Zoom out",
|
|
23
|
+
zoomIn: "Zoom in"
|
|
24
|
+
};
|
|
25
|
+
var pointerSource = (pointerId) => `pointer:${pointerId}`;
|
|
26
|
+
var keySource = (key) => `key:${key}`;
|
|
27
|
+
/**
|
|
28
|
+
* A held action that reports one down/up pair across pointer and keyboard input.
|
|
29
|
+
*
|
|
30
|
+
* The arrangement, rounded scrim group surfaces and release policy translate
|
|
31
|
+
* Adea's on-screen scene controls; host key synthesis and scene APIs are replaced
|
|
32
|
+
* by callbacks.
|
|
33
|
+
*/
|
|
34
|
+
function HoldAction(props) {
|
|
35
|
+
const [pressed, setPressed] = createSignal(false);
|
|
36
|
+
const sources = /* @__PURE__ */ new Set();
|
|
37
|
+
let activeChangeCallback;
|
|
38
|
+
const press = (source) => {
|
|
39
|
+
if (sources.has(source)) return;
|
|
40
|
+
const wasPressed = sources.size > 0;
|
|
41
|
+
sources.add(source);
|
|
42
|
+
if (!wasPressed) {
|
|
43
|
+
setPressed(true);
|
|
44
|
+
activeChangeCallback = props.createChangeCallback();
|
|
45
|
+
activeChangeCallback(true);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const release = (source) => {
|
|
49
|
+
if (!sources.delete(source) || sources.size > 0) return;
|
|
50
|
+
setPressed(false);
|
|
51
|
+
const callback = activeChangeCallback;
|
|
52
|
+
activeChangeCallback = void 0;
|
|
53
|
+
callback?.(false);
|
|
54
|
+
};
|
|
55
|
+
const releaseAll = () => {
|
|
56
|
+
if (sources.size === 0) return;
|
|
57
|
+
sources.clear();
|
|
58
|
+
setPressed(false);
|
|
59
|
+
const callback = activeChangeCallback;
|
|
60
|
+
activeChangeCallback = void 0;
|
|
61
|
+
callback?.(false);
|
|
62
|
+
};
|
|
63
|
+
const onWindowPointerUp = (event) => release(pointerSource(event.pointerId));
|
|
64
|
+
const onWindowBlur = () => releaseAll();
|
|
65
|
+
if (typeof window !== "undefined") {
|
|
66
|
+
window.addEventListener("pointerup", onWindowPointerUp);
|
|
67
|
+
window.addEventListener("blur", onWindowBlur);
|
|
68
|
+
}
|
|
69
|
+
onCleanup(() => {
|
|
70
|
+
releaseAll();
|
|
71
|
+
if (typeof window !== "undefined") {
|
|
72
|
+
window.removeEventListener("pointerup", onWindowPointerUp);
|
|
73
|
+
window.removeEventListener("blur", onWindowBlur);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return createComponent(ActionButton, {
|
|
77
|
+
type: "button",
|
|
78
|
+
variant: "secondary",
|
|
79
|
+
size: "icon-2xl",
|
|
80
|
+
get ["aria-label"]() {
|
|
81
|
+
return props.label;
|
|
82
|
+
},
|
|
83
|
+
get ["aria-pressed"]() {
|
|
84
|
+
return pressed();
|
|
85
|
+
},
|
|
86
|
+
get tooltip() {
|
|
87
|
+
return props.tooltip;
|
|
88
|
+
},
|
|
89
|
+
"class": "touch-none select-none",
|
|
90
|
+
onContextMenu: (event) => event.preventDefault(),
|
|
91
|
+
onPointerDown: (event) => {
|
|
92
|
+
if (event.button !== 0) return;
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
const source = pointerSource(event.pointerId);
|
|
95
|
+
if (sources.has(source)) return;
|
|
96
|
+
try {
|
|
97
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
98
|
+
} catch {}
|
|
99
|
+
press(source);
|
|
100
|
+
},
|
|
101
|
+
onPointerUp: (event) => release(pointerSource(event.pointerId)),
|
|
102
|
+
onPointerCancel: (event) => release(pointerSource(event.pointerId)),
|
|
103
|
+
onLostPointerCapture: (event) => release(pointerSource(event.pointerId)),
|
|
104
|
+
onKeyDown: (event) => {
|
|
105
|
+
if (event.key !== " " && event.key !== "Enter") return;
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
press(keySource(event.key));
|
|
108
|
+
},
|
|
109
|
+
onKeyUp: (event) => {
|
|
110
|
+
if (event.key !== " " && event.key !== "Enter") return;
|
|
111
|
+
event.preventDefault();
|
|
112
|
+
release(keySource(event.key));
|
|
113
|
+
},
|
|
114
|
+
onBlur: releaseAll,
|
|
115
|
+
onClick: (event) => {
|
|
116
|
+
if (event.detail !== 0 || sources.size > 0) return;
|
|
117
|
+
press("activation");
|
|
118
|
+
release("activation");
|
|
119
|
+
},
|
|
120
|
+
get children() {
|
|
121
|
+
return props.children;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Shared movement, jump and zoom controls for a host-rendered scene.
|
|
127
|
+
*
|
|
128
|
+
* Movement and jump callbacks receive pressed/released state from pointer and
|
|
129
|
+
* keyboard input. Zoom callbacks fire on activation. The host owns positioning,
|
|
130
|
+
* scene state and camera behavior.
|
|
131
|
+
*/
|
|
132
|
+
function SceneControls(props) {
|
|
133
|
+
const labels = () => ({
|
|
134
|
+
...DEFAULT_LABELS,
|
|
135
|
+
...props.labels
|
|
136
|
+
});
|
|
137
|
+
return (() => {
|
|
138
|
+
var _el$ = _tmpl$3(), _el$5 = _el$.firstChild;
|
|
139
|
+
insert(_el$, createComponent(Show, {
|
|
140
|
+
get when() {
|
|
141
|
+
return props.onMovementChange;
|
|
142
|
+
},
|
|
143
|
+
get children() {
|
|
144
|
+
var _el$2 = _tmpl$(), _el$4 = _el$2.firstChild.nextSibling;
|
|
145
|
+
insert(_el$2, createComponent(HoldAction, {
|
|
146
|
+
get label() {
|
|
147
|
+
return labels().forward;
|
|
148
|
+
},
|
|
149
|
+
get tooltip() {
|
|
150
|
+
return labels().forwardTooltip;
|
|
151
|
+
},
|
|
152
|
+
createChangeCallback: () => {
|
|
153
|
+
const callback = props.onMovementChange;
|
|
154
|
+
return (pressed) => callback?.("forward", pressed);
|
|
155
|
+
},
|
|
156
|
+
get children() {
|
|
157
|
+
return createComponent(ArrowUp, { "aria-hidden": "true" });
|
|
158
|
+
}
|
|
159
|
+
}), _el$4);
|
|
160
|
+
insert(_el$2, createComponent(HoldAction, {
|
|
161
|
+
get label() {
|
|
162
|
+
return labels().left;
|
|
163
|
+
},
|
|
164
|
+
get tooltip() {
|
|
165
|
+
return labels().leftTooltip;
|
|
166
|
+
},
|
|
167
|
+
createChangeCallback: () => {
|
|
168
|
+
const callback = props.onMovementChange;
|
|
169
|
+
return (pressed) => callback?.("left", pressed);
|
|
170
|
+
},
|
|
171
|
+
get children() {
|
|
172
|
+
return createComponent(ArrowLeft, { "aria-hidden": "true" });
|
|
173
|
+
}
|
|
174
|
+
}), null);
|
|
175
|
+
insert(_el$2, createComponent(HoldAction, {
|
|
176
|
+
get label() {
|
|
177
|
+
return labels().backward;
|
|
178
|
+
},
|
|
179
|
+
get tooltip() {
|
|
180
|
+
return labels().backwardTooltip;
|
|
181
|
+
},
|
|
182
|
+
createChangeCallback: () => {
|
|
183
|
+
const callback = props.onMovementChange;
|
|
184
|
+
return (pressed) => callback?.("backward", pressed);
|
|
185
|
+
},
|
|
186
|
+
get children() {
|
|
187
|
+
return createComponent(ArrowDown, { "aria-hidden": "true" });
|
|
188
|
+
}
|
|
189
|
+
}), null);
|
|
190
|
+
insert(_el$2, createComponent(HoldAction, {
|
|
191
|
+
get label() {
|
|
192
|
+
return labels().right;
|
|
193
|
+
},
|
|
194
|
+
get tooltip() {
|
|
195
|
+
return labels().rightTooltip;
|
|
196
|
+
},
|
|
197
|
+
createChangeCallback: () => {
|
|
198
|
+
const callback = props.onMovementChange;
|
|
199
|
+
return (pressed) => callback?.("right", pressed);
|
|
200
|
+
},
|
|
201
|
+
get children() {
|
|
202
|
+
return createComponent(ArrowRight, { "aria-hidden": "true" });
|
|
203
|
+
}
|
|
204
|
+
}), null);
|
|
205
|
+
effect(() => setAttribute(_el$2, "aria-label", labels().movementGroup));
|
|
206
|
+
return _el$2;
|
|
207
|
+
}
|
|
208
|
+
}), _el$5);
|
|
209
|
+
insert(_el$5, createComponent(Show, {
|
|
210
|
+
get when() {
|
|
211
|
+
return props.onZoomIn || props.onZoomOut;
|
|
212
|
+
},
|
|
213
|
+
get children() {
|
|
214
|
+
var _el$6 = _tmpl$2();
|
|
215
|
+
insert(_el$6, createComponent(Show, {
|
|
216
|
+
get when() {
|
|
217
|
+
return props.onZoomOut;
|
|
218
|
+
},
|
|
219
|
+
get children() {
|
|
220
|
+
return createComponent(ActionButton, {
|
|
221
|
+
type: "button",
|
|
222
|
+
variant: "secondary",
|
|
223
|
+
size: "icon-2xl",
|
|
224
|
+
get ["aria-label"]() {
|
|
225
|
+
return labels().zoomOut;
|
|
226
|
+
},
|
|
227
|
+
get tooltip() {
|
|
228
|
+
return labels().zoomOut;
|
|
229
|
+
},
|
|
230
|
+
onClick: () => props.onZoomOut?.(),
|
|
231
|
+
get children() {
|
|
232
|
+
return createComponent(ZoomOut, { "aria-hidden": "true" });
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}), null);
|
|
237
|
+
insert(_el$6, createComponent(Show, {
|
|
238
|
+
get when() {
|
|
239
|
+
return props.onZoomIn;
|
|
240
|
+
},
|
|
241
|
+
get children() {
|
|
242
|
+
return createComponent(ActionButton, {
|
|
243
|
+
type: "button",
|
|
244
|
+
variant: "secondary",
|
|
245
|
+
size: "icon-2xl",
|
|
246
|
+
get ["aria-label"]() {
|
|
247
|
+
return labels().zoomIn;
|
|
248
|
+
},
|
|
249
|
+
get tooltip() {
|
|
250
|
+
return labels().zoomIn;
|
|
251
|
+
},
|
|
252
|
+
onClick: () => props.onZoomIn?.(),
|
|
253
|
+
get children() {
|
|
254
|
+
return createComponent(ZoomIn, { "aria-hidden": "true" });
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}), null);
|
|
259
|
+
effect(() => setAttribute(_el$6, "aria-label", labels().zoomGroup));
|
|
260
|
+
return _el$6;
|
|
261
|
+
}
|
|
262
|
+
}), null);
|
|
263
|
+
insert(_el$5, createComponent(Show, {
|
|
264
|
+
get when() {
|
|
265
|
+
return props.onJumpChange;
|
|
266
|
+
},
|
|
267
|
+
get children() {
|
|
268
|
+
return createComponent(HoldAction, {
|
|
269
|
+
get label() {
|
|
270
|
+
return labels().jump;
|
|
271
|
+
},
|
|
272
|
+
get tooltip() {
|
|
273
|
+
return labels().jumpTooltip;
|
|
274
|
+
},
|
|
275
|
+
createChangeCallback: () => {
|
|
276
|
+
const callback = props.onJumpChange;
|
|
277
|
+
return (pressed) => callback?.(pressed);
|
|
278
|
+
},
|
|
279
|
+
get children() {
|
|
280
|
+
return createComponent(ArrowUp, { "aria-hidden": "true" });
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}), null);
|
|
285
|
+
return _el$;
|
|
286
|
+
})();
|
|
287
|
+
}
|
|
288
|
+
//#endregion
|
|
289
|
+
export { SceneControls };
|
|
290
|
+
|
|
291
|
+
//# sourceMappingURL=scene-controls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-controls.js","names":["ArrowDown","ArrowLeft","ArrowRight","ArrowUp","ZoomIn","ZoomOut","createSignal","onCleanup","Show","JSX","ActionButton","SceneMovementDirection","SceneControlLabels","movementGroup","forward","forwardTooltip","left","leftTooltip","backward","backwardTooltip","right","rightTooltip","jump","jumpTooltip","zoomGroup","zoomOut","zoomIn","DEFAULT_LABELS","pointerSource","pointerId","keySource","key","SceneControlsProps","onMovementChange","direction","pressed","onJumpChange","onZoomIn","onZoomOut","labels","Partial","HoldActionProps","label","tooltip","createChangeCallback","children","Element","HoldAction","props","setPressed","sources","Set","activeChangeCallback","press","source","has","wasPressed","size","add","release","delete","callback","undefined","releaseAll","clear","onWindowPointerUp","event","PointerEvent","onWindowBlur","window","addEventListener","removeEventListener","_$createComponent","type","variant","aria-label","aria-pressed","onContextMenu","preventDefault","onPointerDown","button","currentTarget","setPointerCapture","onPointerUp","onPointerCancel","onLostPointerCapture","onKeyDown","onKeyUp","onBlur","onClick","detail","SceneControls","_el$","_tmpl$3","_el$5","firstChild","_$insert","when","_el$2","_tmpl$","_el$3","_el$4","nextSibling","_$effect","_$setAttribute","_el$6","_tmpl$2","_$createComponent","_$setAttribute"],"sources":["../../../../src/components/composites/scene-controls/scene-controls.tsx"],"sourcesContent":["import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, ZoomIn, ZoomOut } from 'lucide-solid'\nimport { createSignal, onCleanup, Show, type JSX } from 'solid-js'\nimport { ActionButton } from '../action-button'\n\n/** A host-neutral direction reported while a movement control is held. */\nexport type SceneMovementDirection = 'forward' | 'left' | 'backward' | 'right'\n\n/** Accessible names and tooltip text for the shared scene controls. */\nexport type SceneControlLabels = {\n movementGroup: string\n forward: string\n forwardTooltip: string\n left: string\n leftTooltip: string\n backward: string\n backwardTooltip: string\n right: string\n rightTooltip: string\n jump: string\n jumpTooltip: string\n zoomGroup: string\n zoomOut: string\n zoomIn: string\n}\n\nconst DEFAULT_LABELS: SceneControlLabels = {\n movementGroup: 'Scene movement controls',\n forward: 'Move forward',\n forwardTooltip: 'Hold to move forward',\n left: 'Move left',\n leftTooltip: 'Hold to move left',\n backward: 'Move backward',\n backwardTooltip: 'Hold to move backward',\n right: 'Move right',\n rightTooltip: 'Hold to move right',\n jump: 'Jump',\n jumpTooltip: 'Hold to jump',\n zoomGroup: 'Camera zoom',\n zoomOut: 'Zoom out',\n zoomIn: 'Zoom in',\n}\n\nconst pointerSource = (pointerId: number) => `pointer:${pointerId}`\nconst keySource = (key: string) => `key:${key}`\n\nexport type SceneControlsProps = {\n /** Called on the transition into and out of each held movement direction. */\n onMovementChange?: (direction: SceneMovementDirection, pressed: boolean) => void\n /** Called when the jump action becomes pressed or released. */\n onJumpChange?: (pressed: boolean) => void\n /** Called once when zoom in is activated. */\n onZoomIn?: () => void\n /** Called once when zoom out is activated. */\n onZoomOut?: () => void\n /** Override the default English accessible names and tooltip copy. */\n labels?: Partial<SceneControlLabels>\n}\n\ntype HoldActionProps = {\n label: string\n tooltip: string\n createChangeCallback: () => (pressed: boolean) => void\n children: JSX.Element\n}\n\n/**\n * A held action that reports one down/up pair across pointer and keyboard input.\n *\n * The arrangement, rounded scrim group surfaces and release policy translate\n * Adea's on-screen scene controls; host key synthesis and scene APIs are replaced\n * by callbacks.\n */\nfunction HoldAction(props: HoldActionProps) {\n const [pressed, setPressed] = createSignal(false)\n const sources = new Set<string>()\n let activeChangeCallback: ((pressed: boolean) => void) | undefined\n\n const press = (source: string) => {\n if (sources.has(source)) return\n const wasPressed = sources.size > 0\n sources.add(source)\n if (!wasPressed) {\n setPressed(true)\n activeChangeCallback = props.createChangeCallback()\n activeChangeCallback(true)\n }\n }\n\n const release = (source: string) => {\n if (!sources.delete(source) || sources.size > 0) return\n setPressed(false)\n const callback = activeChangeCallback\n activeChangeCallback = undefined\n callback?.(false)\n }\n\n const releaseAll = () => {\n if (sources.size === 0) return\n sources.clear()\n setPressed(false)\n const callback = activeChangeCallback\n activeChangeCallback = undefined\n callback?.(false)\n }\n\n const onWindowPointerUp = (event: PointerEvent) => release(pointerSource(event.pointerId))\n const onWindowBlur = () => releaseAll()\n\n if (typeof window !== 'undefined') {\n window.addEventListener('pointerup', onWindowPointerUp)\n window.addEventListener('blur', onWindowBlur)\n }\n\n onCleanup(() => {\n releaseAll()\n if (typeof window !== 'undefined') {\n window.removeEventListener('pointerup', onWindowPointerUp)\n window.removeEventListener('blur', onWindowBlur)\n }\n })\n\n return (\n <ActionButton\n type=\"button\"\n variant=\"secondary\"\n size=\"icon-2xl\"\n aria-label={props.label}\n aria-pressed={pressed()}\n tooltip={props.tooltip}\n class=\"touch-none select-none\"\n onContextMenu={(event) => event.preventDefault()}\n onPointerDown={(event) => {\n if (event.button !== 0) return\n event.preventDefault()\n const source = pointerSource(event.pointerId)\n if (sources.has(source)) return\n try {\n event.currentTarget.setPointerCapture(event.pointerId)\n } catch {\n // Pointer capture is not available in every embedded browser. The\n // window pointerup fallback still closes this held action.\n }\n press(source)\n }}\n onPointerUp={(event) => release(pointerSource(event.pointerId))}\n onPointerCancel={(event) => release(pointerSource(event.pointerId))}\n onLostPointerCapture={(event) => release(pointerSource(event.pointerId))}\n onKeyDown={(event) => {\n if (event.key !== ' ' && event.key !== 'Enter') return\n event.preventDefault()\n press(keySource(event.key))\n }}\n onKeyUp={(event) => {\n if (event.key !== ' ' && event.key !== 'Enter') return\n event.preventDefault()\n release(keySource(event.key))\n }}\n onBlur={releaseAll}\n onClick={(event) => {\n // Assistive technology can activate a button without pointer or keyboard\n // down/up events. Treat that activation as one short held action.\n if (event.detail !== 0 || sources.size > 0) return\n press('activation')\n release('activation')\n }}\n >\n {props.children}\n </ActionButton>\n )\n}\n\n/**\n * Shared movement, jump and zoom controls for a host-rendered scene.\n *\n * Movement and jump callbacks receive pressed/released state from pointer and\n * keyboard input. Zoom callbacks fire on activation. The host owns positioning,\n * scene state and camera behavior.\n */\nexport function SceneControls(props: SceneControlsProps) {\n const labels = () => ({ ...DEFAULT_LABELS, ...props.labels })\n\n return (\n <div class=\"flex min-w-0 max-w-full flex-wrap items-end gap-3\">\n <Show when={props.onMovementChange}>\n <div\n role=\"group\"\n aria-label={labels().movementGroup}\n class=\"glass-scrim grid min-w-0 max-w-full grid-cols-3 gap-1.5 rounded-3xl p-2\"\n >\n <span aria-hidden=\"true\" />\n <HoldAction\n label={labels().forward}\n tooltip={labels().forwardTooltip}\n createChangeCallback={() => {\n const callback = props.onMovementChange\n return (pressed) => callback?.('forward', pressed)\n }}\n >\n <ArrowUp aria-hidden=\"true\" />\n </HoldAction>\n <span aria-hidden=\"true\" />\n <HoldAction\n label={labels().left}\n tooltip={labels().leftTooltip}\n createChangeCallback={() => {\n const callback = props.onMovementChange\n return (pressed) => callback?.('left', pressed)\n }}\n >\n <ArrowLeft aria-hidden=\"true\" />\n </HoldAction>\n <HoldAction\n label={labels().backward}\n tooltip={labels().backwardTooltip}\n createChangeCallback={() => {\n const callback = props.onMovementChange\n return (pressed) => callback?.('backward', pressed)\n }}\n >\n <ArrowDown aria-hidden=\"true\" />\n </HoldAction>\n <HoldAction\n label={labels().right}\n tooltip={labels().rightTooltip}\n createChangeCallback={() => {\n const callback = props.onMovementChange\n return (pressed) => callback?.('right', pressed)\n }}\n >\n <ArrowRight aria-hidden=\"true\" />\n </HoldAction>\n </div>\n </Show>\n <div class=\"ml-auto flex min-w-0 max-w-full flex-col items-end gap-2\">\n <Show when={props.onZoomIn || props.onZoomOut}>\n <div\n role=\"group\"\n aria-label={labels().zoomGroup}\n class=\"glass-scrim flex min-w-0 max-w-full flex-wrap gap-1.5 rounded-2xl p-1.5\"\n >\n <Show when={props.onZoomOut}>\n <ActionButton\n type=\"button\"\n variant=\"secondary\"\n size=\"icon-2xl\"\n aria-label={labels().zoomOut}\n tooltip={labels().zoomOut}\n onClick={() => props.onZoomOut?.()}\n >\n <ZoomOut aria-hidden=\"true\" />\n </ActionButton>\n </Show>\n <Show when={props.onZoomIn}>\n <ActionButton\n type=\"button\"\n variant=\"secondary\"\n size=\"icon-2xl\"\n aria-label={labels().zoomIn}\n tooltip={labels().zoomIn}\n onClick={() => props.onZoomIn?.()}\n >\n <ZoomIn aria-hidden=\"true\" />\n </ActionButton>\n </Show>\n </div>\n </Show>\n <Show when={props.onJumpChange}>\n <HoldAction\n label={labels().jump}\n tooltip={labels().jumpTooltip}\n createChangeCallback={() => {\n const callback = props.onJumpChange\n return (pressed) => callback?.(pressed)\n }}\n >\n <ArrowUp aria-hidden=\"true\" />\n </HoldAction>\n </Show>\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -19,7 +19,8 @@ import { type VariantProps } from '#lib/variants';
|
|
|
19
19
|
*/
|
|
20
20
|
export declare const buttonVariants: (props?: ({
|
|
21
21
|
variant?: "link" | "default" | "destructive" | "success" | "secondary" | "outline" | "subtle" | "ghost" | null | undefined;
|
|
22
|
-
size?: "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "icon-2xs" | "icon-xs" | "icon-sm" | "icon-md" | "icon-lg" | "icon-xl" | null | undefined;
|
|
22
|
+
size?: "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "icon-2xs" | "icon-xs" | "icon-sm" | "icon-md" | "icon-lg" | "icon-xl" | "icon-2xl" | null | undefined;
|
|
23
|
+
touchTarget?: "comfortable" | null | undefined;
|
|
23
24
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
24
25
|
type ButtonVariantProps = VariantProps<typeof buttonVariants>;
|
|
25
26
|
export type ButtonProps<T extends ValidComponent = 'button'> = PolymorphicProps<T, ButtonVariantProps & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/button/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAC9E,OAAO,EAAmC,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAC/E,OAAO,EAAwC,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAGvF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/button/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAC9E,OAAO,EAAmC,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAC/E,OAAO,EAAwC,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAGvF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc;;;;8EAmD1B,CAAA;AAED,KAAK,kBAAkB,GAAG,YAAY,CAAC,OAAO,cAAc,CAAC,CAAA;AAE7D,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,cAAc,GAAG,QAAQ,IAAI,gBAAgB,CAC7E,CAAC,EACD,kBAAkB,GAAG;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CACF,CAAA;AAED,wBAAgB,MAAM,CAAC,CAAC,SAAS,cAAc,GAAG,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,kCAuBhF"}
|
|
@@ -44,13 +44,17 @@ var buttonVariants = cva(`${controlInteractive} inline-flex shrink-0 items-cente
|
|
|
44
44
|
md: `${controlSize.md} [&_svg]:size-4`,
|
|
45
45
|
lg: `${controlSize.lg} [&_svg]:size-4`,
|
|
46
46
|
xl: `${controlSize.xl} [&_svg]:size-5`,
|
|
47
|
+
"2xl": `${controlSize["2xl"]} [&_svg]:size-6`,
|
|
47
48
|
"icon-2xs": "size-control-2xs p-0 [&_svg]:size-3",
|
|
48
49
|
"icon-xs": "size-control-xs p-0 [&_svg]:size-3.5",
|
|
49
50
|
"icon-sm": "size-control-sm p-0 [&_svg]:size-3.5",
|
|
50
51
|
"icon-md": "size-control-md p-0 [&_svg]:size-4",
|
|
51
52
|
"icon-lg": "size-control-lg p-0 [&_svg]:size-4",
|
|
52
|
-
"icon-xl": "size-control-xl p-0 [&_svg]:size-5"
|
|
53
|
-
|
|
53
|
+
"icon-xl": "size-control-xl p-0 [&_svg]:size-5",
|
|
54
|
+
"icon-2xl": "size-control-2xl p-0 [&_svg]:size-6"
|
|
55
|
+
},
|
|
56
|
+
/** Opt in to a stable touch target on devices with any coarse pointer. */
|
|
57
|
+
touchTarget: { comfortable: "touch-target-comfortable" }
|
|
54
58
|
},
|
|
55
59
|
defaultVariants: {
|
|
56
60
|
variant: "default",
|
|
@@ -61,6 +65,7 @@ function Button(props) {
|
|
|
61
65
|
const [local, rest] = splitProps(props, [
|
|
62
66
|
"variant",
|
|
63
67
|
"size",
|
|
68
|
+
"touchTarget",
|
|
64
69
|
"class"
|
|
65
70
|
]);
|
|
66
71
|
return createComponent(Polymorphic, mergeProps({
|
|
@@ -69,7 +74,8 @@ function Button(props) {
|
|
|
69
74
|
get ["class"]() {
|
|
70
75
|
return cn(buttonVariants({
|
|
71
76
|
variant: local.variant,
|
|
72
|
-
size: local.size
|
|
77
|
+
size: local.size,
|
|
78
|
+
touchTarget: local.touchTarget
|
|
73
79
|
}), local.class);
|
|
74
80
|
}
|
|
75
81
|
}, rest));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.js","names":["Polymorphic","PolymorphicProps","ComponentProps","splitProps","ValidComponent","cva","controlInteractive","controlSize","VariantProps","cn","buttonVariants","variants","variant","default","secondary","destructive","outline","ghost","subtle","success","link","size","xs","sm","md","lg","xl","defaultVariants","ButtonVariantProps","ButtonProps","T","class","Button","props","local","rest","_$createComponent","_$mergeProps","as","type","_$createComponent","_$mergeProps"],"sources":["../../../../src/components/ui/button/button.tsx"],"sourcesContent":["import { Polymorphic, type PolymorphicProps } from '@kobalte/core/polymorphic'\nimport { type ComponentProps, splitProps, type ValidComponent } from 'solid-js'\nimport { cva, controlInteractive, controlSize, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * Button.\n *\n * One appearance ladder shared by every pressable thing in the system: a\n * button, a toolbar control, a dialog action, and a menu row all draw from the\n * same tokens, so a row of them cannot drift apart.\n *\n * The variants answer \"what is this for\", never \"what colour is it\". A caller\n * that wants a red button writes `variant=\"destructive\"`; the red lives here.\n * That is also what lets the design-system linter tell a caller which variant\n * to use instead of only which class was wrong.\n *\n * Polymorphic: pass `as=\"a\"` (or any component) and the button becomes it\n * while keeping the same styling contract. This replaces the React-era\n * `asChild` primitive, which has no Solid equivalent that preserves props.\n */\nexport const buttonVariants = cva(\n `${controlInteractive} inline-flex shrink-0 items-center justify-center rounded-md font-medium whitespace-nowrap select-none [&_svg]:pointer-events-none [&_svg]:shrink-0`,\n {\n variants: {\n variant: {\n /** The one primary action in a view. */\n default: 'bg-primary text-primary-foreground hover:bg-primary-hover',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-surface-hover',\n /** For the action that destroys something. Never the default. */\n destructive:\n 'bg-destructive-action text-destructive-action-foreground hover:bg-destructive-action/90 focus-visible:ring-destructive-subtle',\n /** A bordered button for a surface that already has a fill. */\n outline:\n 'border border-border bg-transparent text-foreground hover:bg-surface-hover hover:border-input',\n /** No chrome until hover. The default for toolbar and row actions. */\n ghost: 'text-foreground hover:bg-surface-hover',\n /** A tinted primary, for a secondary action inside a primary flow. */\n subtle: 'bg-primary-subtle text-primary hover:bg-primary-subtle/80',\n success: 'bg-success text-success-foreground hover:bg-success/90',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n '2xs': `${controlSize['2xs']} [&_svg]:size-3`,\n xs: `${controlSize.xs} [&_svg]:size-3.5`,\n sm: `${controlSize.sm} [&_svg]:size-3.5`,\n md: `${controlSize.md} [&_svg]:size-4`,\n lg: `${controlSize.lg} [&_svg]:size-4`,\n xl: `${controlSize.xl} [&_svg]:size-5`,\n /* Square, for an icon with no label. The accessible name then has to\n come from `aria-label` or a visually hidden label — an icon-only\n button with neither is the accessibility finding the Storybook lane\n catches on every story. */\n 'icon-2xs': 'size-control-2xs p-0 [&_svg]:size-3',\n 'icon-xs': 'size-control-xs p-0 [&_svg]:size-3.5',\n 'icon-sm': 'size-control-sm p-0 [&_svg]:size-3.5',\n 'icon-md': 'size-control-md p-0 [&_svg]:size-4',\n 'icon-lg': 'size-control-lg p-0 [&_svg]:size-4',\n 'icon-xl': 'size-control-xl p-0 [&_svg]:size-5',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n },\n }\n)\n\ntype ButtonVariantProps = VariantProps<typeof buttonVariants>\n\nexport type ButtonProps<T extends ValidComponent = 'button'> = PolymorphicProps<\n T,\n ButtonVariantProps & {\n class?: string\n }\n>\n\nexport function Button<T extends ValidComponent = 'button'>(props: ButtonProps<T>) {\n const [local, rest] = splitProps(props as ButtonProps, ['variant'
|
|
1
|
+
{"version":3,"file":"button.js","names":["Polymorphic","PolymorphicProps","ComponentProps","splitProps","ValidComponent","cva","controlInteractive","controlSize","VariantProps","cn","buttonVariants","variants","variant","default","secondary","destructive","outline","ghost","subtle","success","link","size","xs","sm","md","lg","xl","touchTarget","comfortable","defaultVariants","ButtonVariantProps","ButtonProps","T","class","Button","props","local","rest","_$createComponent","_$mergeProps","as","type","_$createComponent","_$mergeProps"],"sources":["../../../../src/components/ui/button/button.tsx"],"sourcesContent":["import { Polymorphic, type PolymorphicProps } from '@kobalte/core/polymorphic'\nimport { type ComponentProps, splitProps, type ValidComponent } from 'solid-js'\nimport { cva, controlInteractive, controlSize, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * Button.\n *\n * One appearance ladder shared by every pressable thing in the system: a\n * button, a toolbar control, a dialog action, and a menu row all draw from the\n * same tokens, so a row of them cannot drift apart.\n *\n * The variants answer \"what is this for\", never \"what colour is it\". A caller\n * that wants a red button writes `variant=\"destructive\"`; the red lives here.\n * That is also what lets the design-system linter tell a caller which variant\n * to use instead of only which class was wrong.\n *\n * Polymorphic: pass `as=\"a\"` (or any component) and the button becomes it\n * while keeping the same styling contract. This replaces the React-era\n * `asChild` primitive, which has no Solid equivalent that preserves props.\n */\nexport const buttonVariants = cva(\n `${controlInteractive} inline-flex shrink-0 items-center justify-center rounded-md font-medium whitespace-nowrap select-none [&_svg]:pointer-events-none [&_svg]:shrink-0`,\n {\n variants: {\n variant: {\n /** The one primary action in a view. */\n default: 'bg-primary text-primary-foreground hover:bg-primary-hover',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-surface-hover',\n /** For the action that destroys something. Never the default. */\n destructive:\n 'bg-destructive-action text-destructive-action-foreground hover:bg-destructive-action/90 focus-visible:ring-destructive-subtle',\n /** A bordered button for a surface that already has a fill. */\n outline:\n 'border border-border bg-transparent text-foreground hover:bg-surface-hover hover:border-input',\n /** No chrome until hover. The default for toolbar and row actions. */\n ghost: 'text-foreground hover:bg-surface-hover',\n /** A tinted primary, for a secondary action inside a primary flow. */\n subtle: 'bg-primary-subtle text-primary hover:bg-primary-subtle/80',\n success: 'bg-success text-success-foreground hover:bg-success/90',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n '2xs': `${controlSize['2xs']} [&_svg]:size-3`,\n xs: `${controlSize.xs} [&_svg]:size-3.5`,\n sm: `${controlSize.sm} [&_svg]:size-3.5`,\n md: `${controlSize.md} [&_svg]:size-4`,\n lg: `${controlSize.lg} [&_svg]:size-4`,\n xl: `${controlSize.xl} [&_svg]:size-5`,\n '2xl': `${controlSize['2xl']} [&_svg]:size-6`,\n /* Square, for an icon with no label. The accessible name then has to\n come from `aria-label` or a visually hidden label — an icon-only\n button with neither is the accessibility finding the Storybook lane\n catches on every story. */\n 'icon-2xs': 'size-control-2xs p-0 [&_svg]:size-3',\n 'icon-xs': 'size-control-xs p-0 [&_svg]:size-3.5',\n 'icon-sm': 'size-control-sm p-0 [&_svg]:size-3.5',\n 'icon-md': 'size-control-md p-0 [&_svg]:size-4',\n 'icon-lg': 'size-control-lg p-0 [&_svg]:size-4',\n 'icon-xl': 'size-control-xl p-0 [&_svg]:size-5',\n 'icon-2xl': 'size-control-2xl p-0 [&_svg]:size-6',\n },\n /** Opt in to a stable touch target on devices with any coarse pointer. */\n touchTarget: {\n comfortable: 'touch-target-comfortable',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n },\n }\n)\n\ntype ButtonVariantProps = VariantProps<typeof buttonVariants>\n\nexport type ButtonProps<T extends ValidComponent = 'button'> = PolymorphicProps<\n T,\n ButtonVariantProps & {\n class?: string\n }\n>\n\nexport function Button<T extends ValidComponent = 'button'>(props: ButtonProps<T>) {\n const [local, rest] = splitProps(props as ButtonProps, [\n 'variant',\n 'size',\n 'touchTarget',\n 'class',\n ])\n\n return (\n <Polymorphic\n as=\"button\"\n type=\"button\"\n class={cn(\n buttonVariants({\n variant: local.variant,\n size: local.size,\n touchTarget: local.touchTarget,\n }),\n local.class\n )}\n {...(rest as ComponentProps<'button'>)}\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqBA,IAAaU,iBAAiBL,IAC5B,GAAGC,mBAAkB,sJACrB;CACEK,UAAU;EACRC,SAAS;;GAEPC,SAAS;GACTC,WAAW;;GAEXC,aACE;;GAEFC,SACE;;GAEFC,OAAO;;GAEPC,QAAQ;GACRC,SAAS;GACTC,MAAM;EACR;EACAC,MAAM;GACJ,OAAO,GAAGd,YAAY,OAAM;GAC5Be,IAAI,GAAGf,YAAYe,GAAE;GACrBC,IAAI,GAAGhB,YAAYgB,GAAE;GACrBC,IAAI,GAAGjB,YAAYiB,GAAE;GACrBC,IAAI,GAAGlB,YAAYkB,GAAE;GACrBC,IAAI,GAAGnB,YAAYmB,GAAE;GACrB,OAAO,GAAGnB,YAAY,OAAM;GAK5B,YAAY;GACZ,WAAW;GACX,WAAW;GACX,WAAW;GACX,WAAW;GACX,WAAW;GACX,YAAY;EACd;;EAEAoB,aAAa,EACXC,aAAa,2BACf;CACF;CACAC,iBAAiB;EACfjB,SAAS;EACTS,MAAM;CACR;AACF,CACF;AAWA,SAAgBa,OAA4CC,OAAuB;CACjF,MAAM,CAACC,OAAOC,QAAQlC,WAAWgC,OAAsB;EACrD;EACA;EACA;EACA;CAAO,CACR;CAED,OAAAG,gBACGtC,aAAWuC,WAAA;EACVC,IAAE;EACFC,MAAI;EAAA,KAAA,WAAA;GAAA,OACGhC,GACLC,eAAe;IACbE,SAASwB,MAAMxB;IACfS,MAAMe,MAAMf;IACZM,aAAaS,MAAMT;GACrB,CAAC,GACDS,MAAMH,KACR;EAAC;CAAA,GACII,IAAgC,CAAA;AAG3C"}
|