@opalui/react 0.0.0-stage → 0.0.2

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.
Files changed (72) hide show
  1. package/dist/components/button/button.css +186 -0
  2. package/dist/components/button/button.css.js +1 -0
  3. package/dist/components/button/button.d.ts +26 -0
  4. package/dist/components/button/button.js +39 -0
  5. package/dist/components/button/button.js.map +1 -0
  6. package/dist/components/glass/glass.css +43 -0
  7. package/dist/components/glass/glass.css.js +1 -0
  8. package/dist/components/glass/glass.d.ts +5 -0
  9. package/dist/components/glass/glass.js +19 -0
  10. package/dist/components/glass/glass.js.map +1 -0
  11. package/dist/components/input/input.css +70 -0
  12. package/dist/components/input/input.css.js +1 -0
  13. package/dist/components/input/input.d.ts +17 -0
  14. package/dist/components/input/input.js +36 -0
  15. package/dist/components/input/input.js.map +1 -0
  16. package/dist/components/menu/menu.css +112 -0
  17. package/dist/components/menu/menu.css.js +1 -0
  18. package/dist/components/menu/menu.d.ts +18 -0
  19. package/dist/components/menu/menu.js +125 -0
  20. package/dist/components/menu/menu.js.map +1 -0
  21. package/dist/components/segmented-control/segmented-control.css +136 -0
  22. package/dist/components/segmented-control/segmented-control.css.js +1 -0
  23. package/dist/components/segmented-control/segmented-control.d.ts +21 -0
  24. package/dist/components/segmented-control/segmented-control.js +147 -0
  25. package/dist/components/segmented-control/segmented-control.js.map +1 -0
  26. package/dist/components/select/select.css +164 -0
  27. package/dist/components/select/select.css.js +1 -0
  28. package/dist/components/select/select.d.ts +27 -0
  29. package/dist/components/select/select.js +140 -0
  30. package/dist/components/select/select.js.map +1 -0
  31. package/dist/components/slider/slider.css +114 -0
  32. package/dist/components/slider/slider.css.js +1 -0
  33. package/dist/components/slider/slider.d.ts +17 -0
  34. package/dist/components/slider/slider.js +40 -0
  35. package/dist/components/slider/slider.js.map +1 -0
  36. package/dist/components/switch/switch.css +130 -0
  37. package/dist/components/switch/switch.css.js +1 -0
  38. package/dist/components/switch/switch.d.ts +14 -0
  39. package/dist/components/switch/switch.js +74 -0
  40. package/dist/components/switch/switch.js.map +1 -0
  41. package/dist/components/textarea/textarea.css +56 -0
  42. package/dist/components/textarea/textarea.css.js +1 -0
  43. package/dist/components/textarea/textarea.d.ts +8 -0
  44. package/dist/components/textarea/textarea.js +17 -0
  45. package/dist/components/textarea/textarea.js.map +1 -0
  46. package/dist/index.d.ts +9 -0
  47. package/dist/index.js +10 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/internal/glass/lens.d.ts +44 -0
  50. package/dist/internal/glass/lens.js +116 -0
  51. package/dist/internal/glass/lens.js.map +1 -0
  52. package/dist/internal/glass/map.d.ts +1 -0
  53. package/dist/internal/glass/map.js +48 -0
  54. package/dist/internal/glass/map.js.map +1 -0
  55. package/dist/internal/glass/material.d.ts +55 -0
  56. package/dist/internal/glass/material.js +22 -0
  57. package/dist/internal/glass/material.js.map +1 -0
  58. package/dist/internal/glass/styles.d.ts +2 -0
  59. package/dist/internal/glass/styles.js +4 -0
  60. package/dist/internal/glass/styles.js.map +1 -0
  61. package/dist/internal/glass/support.d.ts +5 -0
  62. package/dist/internal/glass/support.js +8 -0
  63. package/dist/internal/glass/support.js.map +1 -0
  64. package/dist/internal/glass.css +34 -0
  65. package/dist/internal/glass.css.js +1 -0
  66. package/dist/internal/styles.d.ts +2 -0
  67. package/dist/internal/styles.js +9 -0
  68. package/dist/internal/styles.js.map +1 -0
  69. package/dist/styles.css +11 -0
  70. package/dist/styles.css.js +1 -0
  71. package/package.json +90 -4
  72. package/README.md +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segmented-control.js","sourceRoot":"","sources":["../../../src/components/segmented-control/segmented-control.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { forwardRef, useEffect, useRef, useState, type ComponentPropsWithoutRef, type CSSProperties, type ReactNode } from 'react'\nimport { stylesheetHref } from '../../internal/styles.js'\nimport { useGlassLens } from '../../internal/glass/lens.js'\nimport { materials } from '../../internal/glass/material.js'\nimport componentCss from './segmented-control.css?inline'\nimport glassCss from '../../internal/glass/styles.js'\nconst css = `${glassCss}\\n${componentCss}`\n\nconst styleHref = stylesheetHref('segmented-control', css)\n\nexport type SegmentedControlItem = { value: string; label: ReactNode; disabled?: boolean }\nexport type SegmentedControlProps = Omit<ComponentPropsWithoutRef<'div'>, 'children' | 'defaultValue' | 'onChange' | 'role'> & {\n items: readonly SegmentedControlItem[]\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n disabled?: boolean\n}\n\n/** A single-choice control. Supply aria-label or aria-labelledby for its group. */\nexport const SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(function SegmentedControl(\n { items, value, defaultValue, onValueChange, disabled = false, className, style, ...props }, ref,\n) {\n const [internalValue, setInternalValue] = useState(() => defaultValue ?? items.find(item => !item.disabled)?.value)\n const [pressed, setPressed] = useState<string>()\n const [dragPosition, setDragPosition] = useState<number>()\n const [overdrag, setOverdrag] = useState({ stretch: 0, offset: 0 })\n const [rebounding, setRebounding] = useState(false)\n const indicator = useRef<HTMLSpanElement>(null)\n const labelSource = useRef<HTMLSpanElement>(null)\n const glass = useGlassLens(indicator, materials.selection, { source: labelSource, active: pressed !== undefined && !disabled, ink: true })\n const pointerClick = useRef<{ target: HTMLButtonElement; until: number } | null>(null)\n const drag = useRef<{ pointerId: number; startX: number; startIndex: number; position: number; stretch: number; target: HTMLButtonElement } | null>(null)\n\n function nearestEnabled(position: number) {\n return items.reduce((best, item, i) => item.disabled ? best\n : best < 0 || Math.abs(i - position) < Math.abs(best - position) ? i : best, -1)\n }\n\n function movePill(clientX: number) {\n const active = drag.current\n if (!active || disabled) return\n const group = active.target.parentElement\n if (!group) return\n const width = active.target.getBoundingClientRect().width\n if (!width) return\n const direction = getComputedStyle(group).direction === 'rtl' ? -1 : 1\n const rawPosition = active.startIndex + direction * (clientX - active.startX) / width\n const position = Math.max(0, Math.min(items.length - 1, rawPosition))\n const excess = rawPosition - position\n // Increasing resistance caps the stretch at 14% of a segment's width.\n // Shift slightly beyond half the extension so the whole pill drifts with the pull.\n const stretch = 0.14 * (1 - Math.exp(-Math.abs(excess) / 0.9))\n setOverdrag({ stretch, offset: direction * Math.sign(excess) * stretch * width * 0.85 })\n active.position = position\n active.stretch = stretch\n setDragPosition(position)\n const nearest = nearestEnabled(position)\n setPressed(items[nearest]?.value)\n return stretch\n }\n function endDrag() {\n const active = drag.current\n drag.current = null\n setPressed(undefined)\n setDragPosition(undefined)\n setOverdrag({ stretch: 0, offset: 0 })\n setRebounding(false)\n if (active?.target.hasPointerCapture(active.pointerId)) active.target.releasePointerCapture(active.pointerId)\n }\n useEffect(() => {\n window.addEventListener('blur', endDrag)\n return () => window.removeEventListener('blur', endDrag)\n }, [])\n useEffect(() => { if (disabled) endDrag() }, [disabled])\n const selected = value === undefined ? internalValue : value\n const selectedIndex = items.findIndex(item => item.value === selected)\n const pressedIndex = items.findIndex(item => item.value === pressed && !item.disabled)\n const index = dragPosition ?? (pressedIndex >= 0 ? pressedIndex : selectedIndex)\n const firstEnabled = items.findIndex(item => !item.disabled)\n const focusIndex = selectedIndex >= 0 && !items[selectedIndex]?.disabled ? selectedIndex : firstEnabled\n\n function select(next: string) {\n if (disabled || items.find(item => item.value === next)?.disabled || next === selected) return\n if (value === undefined) setInternalValue(next)\n onValueChange?.(next)\n }\n\n function finishDrag(pointerId: number, clientX?: number) {\n const active = drag.current\n if (!active || active.pointerId !== pointerId) return\n // Cancellation/capture loss may carry empty coordinates; keep the last\n // tracked position in those cases instead of reverting to the press origin.\n if (clientX !== undefined) movePill(clientX)\n const nextIndex = nearestEnabled(active.position)\n const next = items[nextIndex]\n const button = active.target.parentElement?.querySelectorAll<HTMLButtonElement>('.opal-segmented-item')[nextIndex]\n pointerClick.current = { target: active.target, until: Date.now() + 500 }\n endDrag()\n if (next) select(next.value)\n setRebounding(active.stretch > 0.005)\n button?.focus({ preventScroll: true })\n }\n\n return <>\n <style href={styleHref} precedence=\"opalui\">{css}</style>\n {glass.filter}\n <div {...props} ref={ref} role=\"radiogroup\" aria-disabled={disabled || undefined}\n className={['opal-segmented', className].filter(Boolean).join(' ')}\n data-lensing={glass.lensing || undefined}\n data-disabled={disabled || undefined}\n data-dragging={pressed !== undefined && !disabled || undefined}\n data-tracking={dragPosition !== undefined && !disabled || undefined}\n data-rebounding={rebounding || undefined}\n style={{ '--opal-segment-count': Math.max(1, items.length), '--opal-segment-index': Math.max(0, index),\n '--opal-segment-stretch': overdrag.stretch, '--opal-segment-pull': `${overdrag.offset}px`, ...glass.surfaceStyle, ...style } as CSSProperties}>\n {index >= 0 && <span ref={indicator} className=\"opal-segmented-indicator\" aria-hidden=\"true\"\n onTransitionEnd={event => { if (event.propertyName === 'transform') setRebounding(false) }} />}\n <span ref={labelSource} className=\"opal-segmented-optical-labels\" aria-hidden=\"true\" style={glass.sourceStyle}>\n {items.map(item => <span key={item.value} className=\"opal-segmented-optical-label\" data-selected={item.value === selected || undefined} data-disabled={item.disabled || undefined}>{item.label}</span>)}\n </span>\n {items.map((item, itemIndex) => <button key={item.value} type=\"button\" role=\"radio\"\n aria-checked={item.value === selected} disabled={disabled || item.disabled}\n tabIndex={!disabled && itemIndex === focusIndex ? 0 : -1}\n className=\"opal-segmented-item\"\n data-pressed={pressed === item.value || undefined}\n onPointerDown={event => {\n if (event.button !== 0 || !event.isPrimary || drag.current || disabled) return\n setRebounding(false)\n event.currentTarget.setPointerCapture(event.pointerId)\n drag.current = { pointerId: event.pointerId, startX: event.clientX, startIndex: itemIndex, position: itemIndex, stretch: 0, target: event.currentTarget }\n setPressed(item.value)\n select(item.value)\n }}\n onPointerMove={event => {\n const active = drag.current\n if (!active || active.pointerId !== event.pointerId || disabled) return\n // Fractional segment positions follow the pointer without selecting\n // intermediate values. The initial grab offset is preserved.\n movePill(event.clientX)\n }}\n onPointerUp={event => {\n // A fast release can arrive without a final pointermove.\n finishDrag(event.pointerId, event.clientX)\n }}\n onPointerCancel={event => finishDrag(event.pointerId)}\n onLostPointerCapture={event => finishDrag(event.pointerId)}\n onDragStart={event => event.preventDefault()}\n onClick={event => {\n setPressed(undefined)\n const pending = pointerClick.current\n pointerClick.current = null\n if (pending?.target === event.currentTarget && Date.now() < pending.until) return\n // Pointer selection already happened on press. Keep keyboard and\n // assistive-technology clicks working without a second callback.\n if (event.detail === 0) select(item.value)\n }}\n onKeyDown={event => {\n pointerClick.current = null\n if (!['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(event.key)) return\n event.preventDefault()\n const group = event.currentTarget.parentElement!\n const rtl = getComputedStyle(group).direction === 'rtl'\n const enabled = items.map((entry, i) => entry.disabled ? -1 : i).filter(i => i >= 0)\n const position = enabled.indexOf(itemIndex)\n const backward = event.key === 'ArrowUp' || event.key === (rtl ? 'ArrowRight' : 'ArrowLeft')\n const next = event.key === 'Home' ? enabled[0] : event.key === 'End' ? enabled.at(-1)\n : enabled[(position + (backward ? -1 : 1) + enabled.length) % enabled.length]\n if (next === undefined) return\n select(items[next]!.value)\n group.querySelectorAll<HTMLButtonElement>('.opal-segmented-item')[next]?.focus()\n }}>\n <span className=\"opal-segmented-label\">{item.label}</span>\n </button>)}\n </div>\n </>\n})\n"]}
@@ -0,0 +1,164 @@
1
+ /* Shared material. Public variables can be set once on a theme container. */
2
+ :where(.opal-glass, .opal-button, .opal-input, .opal-menu-panel, .opal-switch, .opal-slider, .opal-segmented, .opal-textarea, .opal-select) {
3
+ --_opal-glass-rim: var(--opal-glass-rim, inset 0 0 0 .5px rgb(255 255 255 / 7%), inset .65px 1px .65px rgb(255 255 255 / var(--opal-material-rim, .28)), inset -.4px -.65px .8px rgb(255 255 255 / calc(var(--opal-material-rim, .28) * .43)));
4
+ --_opal-glass-edge: 0 0 0 .5px rgb(40 35 30 / calc(var(--opal-material-edge, .5) * .16)), -.65px 0 0 rgb(40 35 30 / calc(var(--opal-material-edge, .5) * .48)), .65px 0 0 rgb(40 35 30 / calc(var(--opal-material-edge, .5) * .48));
5
+ --_opal-glass-shadow: var(--opal-glass-shadow, 0 3px 8px rgb(15 34 47 / 12%));
6
+ }
7
+
8
+ /* One light material for resting controls: clear white face, fine contour,
9
+ a bright inner lip and a broad, low-contrast shadow. */
10
+ :where([data-theme="light"]) {
11
+ --opal-control-background: linear-gradient(180deg, rgb(255 255 255 / 40%) 0%, rgb(255 255 255 / 8%) 32%, rgb(255 255 255 / 4%) 65%, rgb(255 255 255 / 28%) 100%), rgb(255 255 255 / 32%);
12
+ --opal-control-active-background: rgb(255 255 255 / 60%);
13
+ --opal-control-rim-opacity: 1;
14
+ --opal-button-background: var(--opal-control-background);
15
+ --opal-button-hover-background: var(--opal-control-active-background);
16
+ --opal-button-color: #171717;
17
+ --opal-input-background: var(--opal-control-background);
18
+ --opal-input-focus-background: var(--opal-control-active-background);
19
+ --opal-input-color: #171717;
20
+ --opal-segmented-background: var(--opal-control-background);
21
+ --opal-glass-shadow: 0 5px 12px -4px rgb(0 0 0 / 4%);
22
+ --opal-glass-highlight:
23
+ inset 0 0 0 1px rgb(255 255 255 / 78%),
24
+ inset 0 1px 0 rgb(255 255 255 / 100%),
25
+ inset 0 -1px 0 rgb(255 255 255 / 90%);
26
+ }
27
+
28
+ /* Resolve the contour on each surface, where its material settings live.
29
+ edge=.5 reproduces the established 8%/24% light contour exactly. */
30
+ :where([data-theme="light"]) :where(.opal-glass, .opal-button, .opal-input, .opal-menu-panel, .opal-switch, .opal-slider, .opal-segmented, .opal-textarea, .opal-select) {
31
+ --_opal-glass-rim: var(--opal-glass-rim, var(--_opal-glass-edge), var(--opal-glass-highlight));
32
+ }
33
+
34
+ :where(.opal-input,.opal-textarea,.opal-select) { --opal-material-frost:12px; --opal-material-rim:0.22; --opal-material-edge:0.5; }
35
+ :where(.opal-menu-panel) { --opal-material-frost:24px; --opal-material-rim:0.3; --opal-material-edge:0.5; }
36
+
37
+ .opal-menu { display: inline-flex; vertical-align: middle; }
38
+ .opal-menu-panel {
39
+ display: none;
40
+ position: fixed;
41
+ inset: auto;
42
+ margin: 0;
43
+ padding: 6px;
44
+ box-sizing: border-box;
45
+ width: 228px;
46
+ max-width: calc(100vw - 16px);
47
+ max-height: calc(100dvh - 16px);
48
+ overflow: auto;
49
+ z-index: 1000;
50
+ border: 0;
51
+ border-radius: 22px;
52
+ color: var(--opal-menu-color, #202124);
53
+ background: var(--opal-menu-background, rgb(250 250 252 / 86%));
54
+ backdrop-filter: blur(var(--opal-material-frost,24px)) saturate(150%);
55
+ -webkit-backdrop-filter: blur(var(--opal-material-frost,24px)) saturate(150%);
56
+ box-shadow: 0 12px 36px rgb(0 0 0 / 18%), inset 0 0 0 .5px var(--opal-menu-edge, rgb(0 0 0 / 12%)), var(--_opal-glass-rim);
57
+ font: inherit;
58
+ outline: none;
59
+ opacity: 0;
60
+ transform: scale(.6);
61
+ transition: opacity 160ms ease, transform 300ms cubic-bezier(.2,.8,.2,1), display 300ms allow-discrete, overlay 300ms allow-discrete;
62
+ }
63
+ .opal-menu-panel[data-open] { display: block; opacity: 1; transform: scale(1); }
64
+ @starting-style { .opal-menu-panel[data-open] { opacity: 0; transform: scale(.6); } }
65
+ .opal-menu-highlight {
66
+ position: absolute;
67
+ top: 0;
68
+ inset-inline: 6px;
69
+ border-radius: 16px;
70
+ pointer-events: none;
71
+ background: var(--opal-menu-highlight, rgb(0 0 0 / 7%));
72
+ transition: transform 220ms cubic-bezier(.22,.61,.36,1), height 220ms cubic-bezier(.22,.61,.36,1);
73
+ }
74
+ .opal-menu-item {
75
+ position: relative;
76
+ display: flex;
77
+ align-items: center;
78
+ gap: 12px;
79
+ width: 100%;
80
+ min-height: 38px;
81
+ padding: 8px 12px;
82
+ border: 0;
83
+ border-radius: 16px;
84
+ background: transparent;
85
+ color: inherit;
86
+ font: inherit;
87
+ font-size: 14px;
88
+ line-height: 1.35;
89
+ text-align: start;
90
+ cursor: pointer;
91
+ outline: none;
92
+ -webkit-tap-highlight-color: transparent;
93
+ transition: transform 160ms ease;
94
+ }
95
+ .opal-menu-item:active:not(:disabled) { transform: scale(.98); }
96
+ .opal-menu-item:focus-visible { box-shadow: inset 0 0 0 2px var(--opal-focus-color, #2885ff); }
97
+ .opal-menu-item[data-destructive] { color: var(--opal-menu-destructive, #d6293e); }
98
+ .opal-menu-item:disabled { opacity: .4; cursor: default; }
99
+ .opal-menu-icon { display: inline-flex; width: 18px; height: 18px; flex: 0 0 18px; }
100
+ .opal-menu-icon > svg { width: 100%; height: 100%; }
101
+ .opal-menu-separator { height: 1px; margin: 6px 10px; background: var(--opal-menu-edge, rgb(0 0 0 / 10%)); }
102
+ @media (prefers-reduced-motion: reduce) { .opal-menu-panel, .opal-menu-item { transition: none; transform: none; } }
103
+ @media (prefers-reduced-motion: reduce) { .opal-menu-highlight { transition: none; } }
104
+ @media (prefers-reduced-transparency: reduce) { .opal-menu-panel { background: var(--opal-menu-solid, #fafafa); backdrop-filter: none; -webkit-backdrop-filter: none; } }
105
+ @media (forced-colors: active) {
106
+ .opal-menu-panel { background: Canvas; color: CanvasText; border: 1px solid ButtonText; }
107
+ .opal-menu-item:focus { outline: 2px solid Highlight; }
108
+ .opal-menu-highlight { background: transparent; }
109
+ .opal-menu-item[data-destructive] { color: ButtonText; }
110
+ .opal-menu-separator { background: ButtonText; }
111
+ }
112
+
113
+ .opal-select { position: relative; display: inline-flex; width: 360px; max-width: 100%; }
114
+ .opal-select-native { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
115
+ .opal-select-trigger {
116
+ position: relative; display: flex; align-items: center; gap: 10px; box-sizing: border-box;
117
+ width: 100%; min-height: 44px; padding: 12px 16px; border: 0; border-radius: 999px;
118
+ background: var(--opal-input-background, rgb(255 255 255 / 65%)); color: var(--opal-input-color, #171e22);
119
+ box-shadow: var(--opal-input-shadow, var(--_opal-glass-shadow));
120
+ backdrop-filter: blur(var(--opal-material-frost,12px)); -webkit-backdrop-filter: blur(var(--opal-material-frost,12px));
121
+ font: inherit; line-height: 1.25; text-align: start; cursor: pointer;
122
+ }
123
+ .opal-select-trigger::after { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; box-shadow: var(--opal-input-rim, var(--_opal-glass-rim)); opacity: var(--opal-control-rim-opacity, .7); }
124
+ .opal-select-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
125
+ .opal-select-value[data-placeholder] { opacity: .5; }
126
+ .opal-select-chevron, .opal-select-check { width: 18px; height: 18px; flex-shrink: 0; }
127
+ .opal-select-chevron { opacity: .6; transition: transform 280ms cubic-bezier(.22, 1, .36, 1); }
128
+ .opal-select-trigger[aria-expanded="true"] .opal-select-chevron { transform: rotate(180deg); }
129
+ .opal-select-check { margin-inline-start: auto; }
130
+ .opal-select-trigger:focus-visible { outline: 2px solid var(--opal-focus-color, #2885ff); outline-offset: 3px; }
131
+ .opal-select-trigger[aria-invalid="true"] { outline: 2px solid #e5484d; outline-offset: 2px; }
132
+ .opal-select-trigger:disabled { opacity: .4; cursor: not-allowed; }
133
+ .opal-menu-panel.opal-select-panel {
134
+ max-height: min(320px, calc(100dvh - 16px));
135
+ background: var(--opal-input-background, rgb(255 255 255 / 65%));
136
+ color: var(--opal-input-color, #171e22);
137
+ backdrop-filter: blur(var(--opal-material-frost,12px)); -webkit-backdrop-filter: blur(var(--opal-material-frost,12px));
138
+ opacity: 0;
139
+ transform: translateY(var(--opal-select-enter-y, -6px)) scale(.97);
140
+ pointer-events: none;
141
+ transition: opacity 160ms ease, transform 220ms cubic-bezier(.22, 1, .36, 1), display 220ms allow-discrete, overlay 220ms allow-discrete;
142
+ }
143
+ .opal-menu-panel.opal-select-panel[data-open] {
144
+ opacity: 1;
145
+ transform: translateY(0) scale(1);
146
+ pointer-events: auto;
147
+ transition-duration: 200ms, 360ms, 360ms, 360ms;
148
+ }
149
+ @starting-style {
150
+ .opal-menu-panel.opal-select-panel[data-open] {
151
+ opacity: 0;
152
+ transform: translateY(var(--opal-select-enter-y, -6px)) scale(.97);
153
+ }
154
+ }
155
+ @media (prefers-reduced-motion: reduce) {
156
+ .opal-menu-panel.opal-select-panel, .opal-menu-panel.opal-select-panel[data-open], .opal-select-chevron { transition: none; transform: none; }
157
+ }
158
+ @media (prefers-reduced-transparency: reduce) {
159
+ .opal-select-trigger, .opal-menu-panel.opal-select-panel { background: var(--opal-input-solid, #fff); backdrop-filter: none; -webkit-backdrop-filter: none; }
160
+ }
161
+ @media (forced-colors: active) {
162
+ .opal-select-trigger { border: 1px solid ButtonText; }
163
+ .opal-menu-panel.opal-select-panel { background: Canvas; color: CanvasText; }
164
+ }
@@ -0,0 +1 @@
1
+ export default ".opal-select { position: relative; display: inline-flex; width: 360px; max-width: 100%; }\n.opal-select-native { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }\n.opal-select-trigger {\n position: relative; display: flex; align-items: center; gap: 10px; box-sizing: border-box;\n width: 100%; min-height: 44px; padding: 12px 16px; border: 0; border-radius: 999px;\n background: var(--opal-input-background, rgb(255 255 255 / 65%)); color: var(--opal-input-color, #171e22);\n box-shadow: var(--opal-input-shadow, var(--_opal-glass-shadow));\n backdrop-filter: blur(var(--opal-material-frost,12px)); -webkit-backdrop-filter: blur(var(--opal-material-frost,12px));\n font: inherit; line-height: 1.25; text-align: start; cursor: pointer;\n}\n.opal-select-trigger::after { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; box-shadow: var(--opal-input-rim, var(--_opal-glass-rim)); opacity: var(--opal-control-rim-opacity, .7); }\n.opal-select-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.opal-select-value[data-placeholder] { opacity: .5; }\n.opal-select-chevron, .opal-select-check { width: 18px; height: 18px; flex-shrink: 0; }\n.opal-select-chevron { opacity: .6; transition: transform 280ms cubic-bezier(.22, 1, .36, 1); }\n.opal-select-trigger[aria-expanded=\"true\"] .opal-select-chevron { transform: rotate(180deg); }\n.opal-select-check { margin-inline-start: auto; }\n.opal-select-trigger:focus-visible { outline: 2px solid var(--opal-focus-color, #2885ff); outline-offset: 3px; }\n.opal-select-trigger[aria-invalid=\"true\"] { outline: 2px solid #e5484d; outline-offset: 2px; }\n.opal-select-trigger:disabled { opacity: .4; cursor: not-allowed; }\n.opal-menu-panel.opal-select-panel {\n max-height: min(320px, calc(100dvh - 16px));\n background: var(--opal-input-background, rgb(255 255 255 / 65%));\n color: var(--opal-input-color, #171e22);\n backdrop-filter: blur(var(--opal-material-frost,12px)); -webkit-backdrop-filter: blur(var(--opal-material-frost,12px));\n opacity: 0;\n transform: translateY(var(--opal-select-enter-y, -6px)) scale(.97);\n pointer-events: none;\n transition: opacity 160ms ease, transform 220ms cubic-bezier(.22, 1, .36, 1), display 220ms allow-discrete, overlay 220ms allow-discrete;\n}\n.opal-menu-panel.opal-select-panel[data-open] {\n opacity: 1;\n transform: translateY(0) scale(1);\n pointer-events: auto;\n transition-duration: 200ms, 360ms, 360ms, 360ms;\n}\n@starting-style {\n .opal-menu-panel.opal-select-panel[data-open] {\n opacity: 0;\n transform: translateY(var(--opal-select-enter-y, -6px)) scale(.97);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .opal-menu-panel.opal-select-panel, .opal-menu-panel.opal-select-panel[data-open], .opal-select-chevron { transition: none; transform: none; }\n}\n@media (prefers-reduced-transparency: reduce) {\n .opal-select-trigger, .opal-menu-panel.opal-select-panel { background: var(--opal-input-solid, #fff); backdrop-filter: none; -webkit-backdrop-filter: none; }\n}\n@media (forced-colors: active) {\n .opal-select-trigger { border: 1px solid ButtonText; }\n .opal-menu-panel.opal-select-panel { background: Canvas; color: CanvasText; }\n}\n";
@@ -0,0 +1,27 @@
1
+ import { type CSSProperties, type ReactNode } from 'react';
2
+ export type SelectItem = {
3
+ value: string;
4
+ label: string;
5
+ icon?: ReactNode;
6
+ disabled?: boolean;
7
+ };
8
+ export type SelectProps = {
9
+ items: readonly SelectItem[];
10
+ value?: string;
11
+ defaultValue?: string;
12
+ onValueChange?: (value: string) => void;
13
+ placeholder?: string;
14
+ disabled?: boolean;
15
+ required?: boolean;
16
+ name?: string;
17
+ form?: string;
18
+ id?: string;
19
+ 'aria-label'?: string;
20
+ 'aria-labelledby'?: string;
21
+ 'aria-describedby'?: string;
22
+ 'aria-invalid'?: boolean | 'true' | 'false' | 'grammar' | 'spelling';
23
+ className?: string;
24
+ style?: CSSProperties;
25
+ };
26
+ /** Single selection with a menu-style listbox and native form participation. */
27
+ export declare const Select: import("react").ForwardRefExoticComponent<SelectProps & import("react").RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,140 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { forwardRef, useEffect, useId, useImperativeHandle, useRef, useState } from 'react';
4
+ import { stylesheetHref } from '../../internal/styles.js';
5
+ import componentCss from './select.css.js';
6
+ import menuCss from '../menu/menu.css.js';
7
+ import glassCss from '../../internal/glass/styles.js';
8
+ const css = `${glassCss}\n${menuCss}\n${componentCss}`;
9
+ const styleHref = stylesheetHref('select', css);
10
+ /** Single selection with a menu-style listbox and native form participation. */
11
+ export const Select = forwardRef(function Select({ items, value, defaultValue = '', onValueChange, placeholder = 'Select an option', disabled, required, name, form, id, className, style, ...aria }, ref) {
12
+ const uid = useId();
13
+ const trigger = useRef(null);
14
+ const panel = useRef(null);
15
+ const native = useRef(null);
16
+ useImperativeHandle(ref, () => trigger.current, []);
17
+ const [internal, setInternal] = useState(defaultValue);
18
+ const [invalid, setInvalid] = useState(false);
19
+ const [open, setOpen] = useState(false);
20
+ const [highlight, setHighlight] = useState(null);
21
+ const search = useRef({ text: '', time: 0 });
22
+ const selected = value ?? internal;
23
+ const selectedItem = items.find(item => item.value === selected);
24
+ const options = () => Array.from(panel.current?.querySelectorAll('[role="option"]:not(:disabled)') ?? []);
25
+ function close(restore = true) {
26
+ if (panel.current)
27
+ delete panel.current.dataset.open;
28
+ panel.current?.hidePopover?.();
29
+ setOpen(false);
30
+ if (restore)
31
+ trigger.current?.focus({ preventScroll: true });
32
+ }
33
+ function position() {
34
+ const popup = panel.current;
35
+ const button = trigger.current;
36
+ if (!popup || !button)
37
+ return;
38
+ const rect = button.getBoundingClientRect();
39
+ popup.style.width = `${Math.min(Math.max(rect.width, 200), window.innerWidth - 16)}px`;
40
+ const below = window.innerHeight - rect.bottom - 14;
41
+ const above = rect.top - 14;
42
+ const upwards = below < Math.min(popup.scrollHeight, 240) && above > below;
43
+ popup.style.maxHeight = `${Math.max(44, Math.min(320, upwards ? above : below))}px`;
44
+ popup.style.left = `${Math.max(8, Math.min(rect.left, window.innerWidth - popup.offsetWidth - 8))}px`;
45
+ popup.style.top = `${Math.max(8, upwards ? rect.top - popup.offsetHeight - 6 : rect.bottom + 6)}px`;
46
+ popup.style.transformOrigin = upwards ? 'bottom center' : 'top center';
47
+ popup.style.setProperty('--opal-select-enter-y', upwards ? '6px' : '-6px');
48
+ }
49
+ function show(last = false) {
50
+ if (disabled || !panel.current)
51
+ return;
52
+ panel.current.dataset.open = 'true';
53
+ position();
54
+ panel.current.showPopover?.();
55
+ setOpen(true);
56
+ search.current = { text: '', time: 0 };
57
+ const enabled = options();
58
+ const target = enabled.find(item => item.dataset.value === selected) ?? (last ? enabled.at(-1) : enabled[0]);
59
+ (target ?? panel.current).focus({ preventScroll: true });
60
+ target?.scrollIntoView({ block: 'nearest' });
61
+ }
62
+ function choose(next) {
63
+ if (value === undefined)
64
+ setInternal(next);
65
+ if (next !== selected)
66
+ onValueChange?.(next);
67
+ setInvalid(false);
68
+ close();
69
+ }
70
+ useEffect(() => {
71
+ const element = native.current;
72
+ const reset = (event) => queueMicrotask(() => {
73
+ if (event.defaultPrevented)
74
+ return;
75
+ if (value === undefined)
76
+ setInternal(defaultValue);
77
+ setInvalid(false);
78
+ });
79
+ element?.form?.addEventListener('reset', reset);
80
+ return () => element?.form?.removeEventListener('reset', reset);
81
+ }, [value, defaultValue, form]);
82
+ useEffect(() => { setInvalid(false); }, [selected]);
83
+ useEffect(() => { if (disabled)
84
+ close(false); }, [disabled]);
85
+ useEffect(() => {
86
+ if (!open)
87
+ return;
88
+ const outside = (event) => { if (!panel.current?.contains(event.target) && !trigger.current?.contains(event.target))
89
+ close(false); };
90
+ const blur = () => close(false);
91
+ const observer = new ResizeObserver(() => {
92
+ position();
93
+ const active = document.activeElement;
94
+ if (active instanceof HTMLButtonElement && panel.current?.contains(active))
95
+ setHighlight({ top: active.offsetTop, height: active.offsetHeight });
96
+ });
97
+ if (trigger.current)
98
+ observer.observe(trigger.current);
99
+ options().forEach(item => observer.observe(item));
100
+ document.addEventListener('pointerdown', outside);
101
+ window.addEventListener('resize', position);
102
+ window.addEventListener('scroll', position, true);
103
+ window.addEventListener('blur', blur);
104
+ return () => { observer.disconnect(); document.removeEventListener('pointerdown', outside); window.removeEventListener('resize', position); window.removeEventListener('scroll', position, true); window.removeEventListener('blur', blur); };
105
+ }, [open, items]);
106
+ return _jsxs(_Fragment, { children: [_jsx("style", { href: styleHref, precedence: "opalui", children: css }), _jsxs("span", { className: ['opal-select', className].filter(Boolean).join(' '), style: style, children: [_jsxs("select", { ref: native, className: "opal-select-native", tabIndex: -1, "aria-hidden": "true", name: name, form: form, required: required, disabled: disabled, value: selected, onChange: event => choose(event.currentTarget.value), onInvalid: event => { event.preventDefault(); trigger.current?.focus(); setInvalid(true); }, children: [!items.some(item => item.value === '') && _jsx("option", { value: "", children: placeholder }), items.map(item => _jsx("option", { value: item.value, disabled: item.disabled, children: item.label }, item.value))] }), _jsxs("button", { ...aria, ref: trigger, id: id ?? `${uid}-trigger`, className: "opal-select-trigger", type: "button", disabled: disabled, "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": `${uid}-list`, "aria-required": required || undefined, "aria-invalid": aria['aria-invalid'] ?? (invalid || undefined), onClick: () => open ? close() : show(), onKeyDown: event => { if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
107
+ event.preventDefault();
108
+ show(event.key === 'ArrowUp');
109
+ } }, children: [selectedItem?.icon && _jsx("span", { className: "opal-menu-icon", "aria-hidden": "true", children: selectedItem.icon }), _jsx("span", { className: "opal-select-value", "data-placeholder": !selectedItem || undefined, children: selectedItem?.label ?? placeholder }), _jsx("svg", { className: "opal-select-chevron", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", "aria-hidden": "true", children: _jsx("path", { d: "m6 9 6 6 6-6" }) })] }), _jsxs("div", { ref: panel, id: `${uid}-list`, role: "listbox", tabIndex: -1, "aria-label": aria['aria-label'], "aria-labelledby": aria['aria-labelledby'] ?? (!aria['aria-label'] ? (id ?? `${uid}-trigger`) : undefined), className: "opal-menu-panel opal-select-panel", popover: "manual", "data-open": open || undefined, onKeyDown: event => {
110
+ const enabled = options();
111
+ const current = enabled.indexOf(document.activeElement);
112
+ if (event.key === 'Escape') {
113
+ event.preventDefault();
114
+ event.stopPropagation();
115
+ close();
116
+ return;
117
+ }
118
+ if (event.key === 'Tab') {
119
+ close();
120
+ return;
121
+ }
122
+ if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) {
123
+ event.preventDefault();
124
+ const next = event.key === 'Home' ? 0 : event.key === 'End' ? enabled.length - 1 : (current + (event.key === 'ArrowDown' ? 1 : -1) + enabled.length) % enabled.length;
125
+ enabled[next]?.focus();
126
+ return;
127
+ }
128
+ if (event.key.length === 1 && event.key !== ' ' && !event.ctrlKey && !event.metaKey && !event.altKey) {
129
+ event.preventDefault();
130
+ const now = Date.now();
131
+ search.current.text = (now - search.current.time < 600 ? search.current.text : '') + event.key.toLowerCase();
132
+ search.current.time = now;
133
+ const text = new Set(search.current.text).size === 1 ? event.key.toLowerCase() : search.current.text;
134
+ const ordered = [...enabled.slice(current + 1), ...enabled.slice(0, current + 1)];
135
+ ordered.find(item => item.dataset.label?.toLowerCase().startsWith(text))?.focus();
136
+ }
137
+ }, children: [highlight && _jsx("span", { className: "opal-menu-highlight", "aria-hidden": "true", style: { transform: `translateY(${highlight.top}px)`, height: highlight.height } }), items.map(item => _jsxs("button", { type: "button", role: "option", tabIndex: -1, "aria-selected": item.value === selected, disabled: item.disabled, "data-value": item.value, "data-label": item.label, className: "opal-menu-item", onFocus: event => setHighlight({ top: event.currentTarget.offsetTop, height: event.currentTarget.offsetHeight }), onPointerMove: event => { if (event.pointerType === 'mouse' && !item.disabled && document.activeElement !== event.currentTarget)
138
+ event.currentTarget.focus({ preventScroll: true }); }, onClick: () => choose(item.value), children: [item.icon && _jsx("span", { className: "opal-menu-icon", "aria-hidden": "true", children: item.icon }), _jsx("span", { children: item.label }), item.value === selected && _jsx("svg", { className: "opal-select-check", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", "aria-hidden": "true", children: _jsx("path", { d: "m5 12 4 4L19 6" }) })] }, item.value))] })] })] });
139
+ });
140
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/components/select/select.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { forwardRef, useEffect, useId, useImperativeHandle, useRef, useState, type CSSProperties, type ReactNode } from 'react'\nimport { stylesheetHref } from '../../internal/styles.js'\nimport componentCss from './select.css?inline'\nimport menuCss from '../menu/menu.css?inline'\nimport glassCss from '../../internal/glass/styles.js'\nconst css = `${glassCss}\\n${menuCss}\\n${componentCss}`\nconst styleHref = stylesheetHref('select', css)\nexport type SelectItem = { value: string; label: string; icon?: ReactNode; disabled?: boolean }\nexport type SelectProps = {\n items: readonly SelectItem[]\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n placeholder?: string\n disabled?: boolean\n required?: boolean\n name?: string\n form?: string\n id?: string\n 'aria-label'?: string\n 'aria-labelledby'?: string\n 'aria-describedby'?: string\n 'aria-invalid'?: boolean | 'true' | 'false' | 'grammar' | 'spelling'\n className?: string\n style?: CSSProperties\n}\n\n/** Single selection with a menu-style listbox and native form participation. */\nexport const Select = forwardRef<HTMLButtonElement, SelectProps>(function Select(\n { items, value, defaultValue = '', onValueChange, placeholder = 'Select an option', disabled, required, name, form, id, className, style, ...aria }, ref,\n) {\n const uid = useId()\n const trigger = useRef<HTMLButtonElement>(null)\n const panel = useRef<HTMLDivElement>(null)\n const native = useRef<HTMLSelectElement>(null)\n useImperativeHandle(ref, () => trigger.current!, [])\n const [internal, setInternal] = useState(defaultValue)\n const [invalid, setInvalid] = useState(false)\n const [open, setOpen] = useState(false)\n const [highlight, setHighlight] = useState<{ top: number; height: number } | null>(null)\n const search = useRef({ text: '', time: 0 })\n const selected = value ?? internal\n const selectedItem = items.find(item => item.value === selected)\n const options = () => Array.from(panel.current?.querySelectorAll<HTMLButtonElement>('[role=\"option\"]:not(:disabled)') ?? [])\n function close(restore = true) {\n if (panel.current) delete panel.current.dataset.open\n panel.current?.hidePopover?.()\n setOpen(false)\n if (restore) trigger.current?.focus({ preventScroll: true })\n }\n function position() {\n const popup = panel.current\n const button = trigger.current\n if (!popup || !button) return\n const rect = button.getBoundingClientRect()\n popup.style.width = `${Math.min(Math.max(rect.width, 200), window.innerWidth - 16)}px`\n const below = window.innerHeight - rect.bottom - 14\n const above = rect.top - 14\n const upwards = below < Math.min(popup.scrollHeight, 240) && above > below\n popup.style.maxHeight = `${Math.max(44, Math.min(320, upwards ? above : below))}px`\n popup.style.left = `${Math.max(8, Math.min(rect.left, window.innerWidth - popup.offsetWidth - 8))}px`\n popup.style.top = `${Math.max(8, upwards ? rect.top - popup.offsetHeight - 6 : rect.bottom + 6)}px`\n popup.style.transformOrigin = upwards ? 'bottom center' : 'top center'\n popup.style.setProperty('--opal-select-enter-y', upwards ? '6px' : '-6px')\n }\n function show(last = false) {\n if (disabled || !panel.current) return\n panel.current.dataset.open = 'true'\n position()\n panel.current.showPopover?.()\n setOpen(true)\n search.current = { text: '', time: 0 }\n const enabled = options()\n const target = enabled.find(item => item.dataset.value === selected) ?? (last ? enabled.at(-1) : enabled[0])\n ;(target ?? panel.current).focus({ preventScroll: true })\n target?.scrollIntoView({ block: 'nearest' })\n }\n function choose(next: string) {\n if (value === undefined) setInternal(next)\n if (next !== selected) onValueChange?.(next)\n setInvalid(false)\n close()\n }\n useEffect(() => {\n const element = native.current\n const reset = (event: Event) => queueMicrotask(() => {\n if (event.defaultPrevented) return\n if (value === undefined) setInternal(defaultValue)\n setInvalid(false)\n })\n element?.form?.addEventListener('reset', reset)\n return () => element?.form?.removeEventListener('reset', reset)\n }, [value, defaultValue, form])\n useEffect(() => { setInvalid(false) }, [selected])\n useEffect(() => { if (disabled) close(false) }, [disabled])\n useEffect(() => {\n if (!open) return\n const outside = (event: PointerEvent) => { if (!panel.current?.contains(event.target as Node) && !trigger.current?.contains(event.target as Node)) close(false) }\n const blur = () => close(false)\n const observer = new ResizeObserver(() => {\n position()\n const active = document.activeElement\n if (active instanceof HTMLButtonElement && panel.current?.contains(active)) setHighlight({ top: active.offsetTop, height: active.offsetHeight })\n })\n if (trigger.current) observer.observe(trigger.current)\n options().forEach(item => observer.observe(item))\n document.addEventListener('pointerdown', outside)\n window.addEventListener('resize', position)\n window.addEventListener('scroll', position, true)\n window.addEventListener('blur', blur)\n return () => { observer.disconnect(); document.removeEventListener('pointerdown', outside); window.removeEventListener('resize', position); window.removeEventListener('scroll', position, true); window.removeEventListener('blur', blur) }\n }, [open, items])\n return <>\n <style href={styleHref} precedence=\"opalui\">{css}</style>\n <span className={['opal-select', className].filter(Boolean).join(' ')} style={style}>\n <select ref={native} className=\"opal-select-native\" tabIndex={-1} aria-hidden=\"true\" name={name} form={form} required={required} disabled={disabled} value={selected}\n onChange={event => choose(event.currentTarget.value)} onInvalid={event => { event.preventDefault(); trigger.current?.focus(); setInvalid(true) }}>\n {!items.some(item => item.value === '') && <option value=\"\">{placeholder}</option>}\n {items.map(item => <option key={item.value} value={item.value} disabled={item.disabled}>{item.label}</option>)}\n </select>\n <button {...aria} ref={trigger} id={id ?? `${uid}-trigger`} className=\"opal-select-trigger\" type=\"button\" disabled={disabled}\n aria-haspopup=\"listbox\" aria-expanded={open} aria-controls={`${uid}-list`} aria-required={required || undefined} aria-invalid={aria['aria-invalid'] ?? (invalid || undefined)}\n onClick={() => open ? close() : show()}\n onKeyDown={event => { if (event.key === 'ArrowDown' || event.key === 'ArrowUp') { event.preventDefault(); show(event.key === 'ArrowUp') } }}>\n {selectedItem?.icon && <span className=\"opal-menu-icon\" aria-hidden=\"true\">{selectedItem.icon}</span>}\n <span className=\"opal-select-value\" data-placeholder={!selectedItem || undefined}>{selectedItem?.label ?? placeholder}</span>\n <svg className=\"opal-select-chevron\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" aria-hidden=\"true\"><path d=\"m6 9 6 6 6-6\" /></svg>\n </button>\n <div ref={panel} id={`${uid}-list`} role=\"listbox\" tabIndex={-1} aria-label={aria['aria-label']} aria-labelledby={aria['aria-labelledby'] ?? (!aria['aria-label'] ? (id ?? `${uid}-trigger`) : undefined)}\n className=\"opal-menu-panel opal-select-panel\" popover=\"manual\" data-open={open || undefined}\n onKeyDown={event => {\n const enabled = options()\n const current = enabled.indexOf(document.activeElement as HTMLButtonElement)\n if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); close(); return }\n if (event.key === 'Tab') { close(); return }\n if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) {\n event.preventDefault()\n const next = event.key === 'Home' ? 0 : event.key === 'End' ? enabled.length - 1 : (current + (event.key === 'ArrowDown' ? 1 : -1) + enabled.length) % enabled.length\n enabled[next]?.focus(); return\n }\n if (event.key.length === 1 && event.key !== ' ' && !event.ctrlKey && !event.metaKey && !event.altKey) {\n event.preventDefault()\n const now = Date.now()\n search.current.text = (now - search.current.time < 600 ? search.current.text : '') + event.key.toLowerCase()\n search.current.time = now\n const text = new Set(search.current.text).size === 1 ? event.key.toLowerCase() : search.current.text\n const ordered = [...enabled.slice(current + 1), ...enabled.slice(0, current + 1)]\n ordered.find(item => item.dataset.label?.toLowerCase().startsWith(text))?.focus()\n }\n }}>\n {highlight && <span className=\"opal-menu-highlight\" aria-hidden=\"true\" style={{ transform: `translateY(${highlight.top}px)`, height: highlight.height }} />}\n {items.map(item => <button key={item.value} type=\"button\" role=\"option\" tabIndex={-1} aria-selected={item.value === selected} disabled={item.disabled}\n data-value={item.value} data-label={item.label} className=\"opal-menu-item\"\n onFocus={event => setHighlight({ top: event.currentTarget.offsetTop, height: event.currentTarget.offsetHeight })}\n onPointerMove={event => { if (event.pointerType === 'mouse' && !item.disabled && document.activeElement !== event.currentTarget) event.currentTarget.focus({ preventScroll: true }) }}\n onClick={() => choose(item.value)}>\n {item.icon && <span className=\"opal-menu-icon\" aria-hidden=\"true\">{item.icon}</span>}\n <span>{item.label}</span>\n {item.value === selected && <svg className=\"opal-select-check\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" aria-hidden=\"true\"><path d=\"m5 12 4 4L19 6\" /></svg>}\n </button>)}\n </div>\n </span>\n </>\n})\n"]}
@@ -0,0 +1,114 @@
1
+ /* Shared material. Public variables can be set once on a theme container. */
2
+ :where(.opal-glass, .opal-button, .opal-input, .opal-menu-panel, .opal-switch, .opal-slider, .opal-segmented, .opal-textarea, .opal-select) {
3
+ --_opal-glass-rim: var(--opal-glass-rim, inset 0 0 0 .5px rgb(255 255 255 / 7%), inset .65px 1px .65px rgb(255 255 255 / var(--opal-material-rim, .28)), inset -.4px -.65px .8px rgb(255 255 255 / calc(var(--opal-material-rim, .28) * .43)));
4
+ --_opal-glass-edge: 0 0 0 .5px rgb(40 35 30 / calc(var(--opal-material-edge, .5) * .16)), -.65px 0 0 rgb(40 35 30 / calc(var(--opal-material-edge, .5) * .48)), .65px 0 0 rgb(40 35 30 / calc(var(--opal-material-edge, .5) * .48));
5
+ --_opal-glass-shadow: var(--opal-glass-shadow, 0 3px 8px rgb(15 34 47 / 12%));
6
+ }
7
+
8
+ /* One light material for resting controls: clear white face, fine contour,
9
+ a bright inner lip and a broad, low-contrast shadow. */
10
+ :where([data-theme="light"]) {
11
+ --opal-control-background: linear-gradient(180deg, rgb(255 255 255 / 40%) 0%, rgb(255 255 255 / 8%) 32%, rgb(255 255 255 / 4%) 65%, rgb(255 255 255 / 28%) 100%), rgb(255 255 255 / 32%);
12
+ --opal-control-active-background: rgb(255 255 255 / 60%);
13
+ --opal-control-rim-opacity: 1;
14
+ --opal-button-background: var(--opal-control-background);
15
+ --opal-button-hover-background: var(--opal-control-active-background);
16
+ --opal-button-color: #171717;
17
+ --opal-input-background: var(--opal-control-background);
18
+ --opal-input-focus-background: var(--opal-control-active-background);
19
+ --opal-input-color: #171717;
20
+ --opal-segmented-background: var(--opal-control-background);
21
+ --opal-glass-shadow: 0 5px 12px -4px rgb(0 0 0 / 4%);
22
+ --opal-glass-highlight:
23
+ inset 0 0 0 1px rgb(255 255 255 / 78%),
24
+ inset 0 1px 0 rgb(255 255 255 / 100%),
25
+ inset 0 -1px 0 rgb(255 255 255 / 90%);
26
+ }
27
+
28
+ /* Resolve the contour on each surface, where its material settings live.
29
+ edge=.5 reproduces the established 8%/24% light contour exactly. */
30
+ :where([data-theme="light"]) :where(.opal-glass, .opal-button, .opal-input, .opal-menu-panel, .opal-switch, .opal-slider, .opal-segmented, .opal-textarea, .opal-select) {
31
+ --_opal-glass-rim: var(--opal-glass-rim, var(--_opal-glass-edge), var(--opal-glass-highlight));
32
+ }
33
+
34
+ :where(.opal-input,.opal-textarea,.opal-select) { --opal-material-frost:12px; --opal-material-rim:0.22; --opal-material-edge:0.5; }
35
+ :where(.opal-menu-panel) { --opal-material-frost:24px; --opal-material-rim:0.3; --opal-material-edge:0.5; }
36
+
37
+
38
+ .opal-slider-track, .opal-slider-thumb {
39
+ position:absolute; pointer-events:none; box-sizing:border-box;
40
+ --opal-slider-center:calc(18px + (100cqw - 36px) * var(--opal-slider-position));
41
+ --opal-slider-fill:calc(18px + (100cqw - 36px) * var(--opal-slider-fraction));
42
+ }
43
+ .opal-slider {
44
+ position: relative; display: inline-block; vertical-align: middle;
45
+ width: 330px; max-width: 100%; height: 44px;
46
+ container-type: inline-size;
47
+ --opal-slider-position: var(--opal-slider-fraction);
48
+ --opal-slider-direction: to right;
49
+ }
50
+ .opal-slider:dir(rtl) { --opal-slider-direction: to left; --opal-slider-position: calc(1 - var(--opal-slider-fraction)); }
51
+ .opal-slider-input {
52
+ appearance: none; -webkit-appearance: none; position: absolute; z-index: 3;
53
+ inset: 0; width: 100%; height: 44px; margin: 0; padding: 0;
54
+ opacity: 0; background: transparent; border: 0; cursor: pointer; touch-action: pan-y;
55
+ }
56
+ /* Retain native range interaction and its exact 36px thumb travel. */
57
+ .opal-slider-input::-webkit-slider-runnable-track { height: 6px; }
58
+ .opal-slider-input::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; width: 36px; height: 24px; margin-top: -9px; border: 0; }
59
+ .opal-slider-input::-moz-range-track { height: 6px; }
60
+ .opal-slider-input::-moz-range-thumb { width: 36px; height: 24px; border: 0; }
61
+ .opal-slider-track {
62
+ height: 6px; border-radius: 999px;
63
+ background: var(--opal-slider-track, rgb(118 118 128 / 24%));
64
+ }
65
+ .opal-slider-track::before {
66
+ content: ''; position: absolute; inset-block: 0; inset-inline-start: 0;
67
+ width: var(--opal-slider-fill); border-radius: inherit;
68
+ background: var(--opal-slider-tint, #009dff);
69
+ }
70
+ .opal-slider-track { top: 19px; width: 100%; }
71
+ .opal-slider-thumb {
72
+ top: 10px; left: calc(var(--opal-slider-center) - 18px);
73
+ width: 36px; height: 24px; border-radius: 999px; background: #fff;
74
+ box-shadow: 0 1px 4px rgb(0 0 0 / 14%), inset 0 0 0 .5px rgb(0 0 0 / 5%);
75
+ transition: transform 380ms cubic-bezier(.22,.61,.36,1), background-color 240ms ease, box-shadow 300ms ease;
76
+ }
77
+ /* Put the glass surface above the reproduced track, so its pixels are
78
+ softened and brightened too, rather than painted over the glass. */
79
+ .opal-slider-thumb::after {
80
+ content: ''; position: absolute; inset: 0; border-radius: inherit;
81
+ pointer-events: none; opacity: 0;
82
+ background: linear-gradient(to bottom, rgb(255 255 255 / 3%) 30%, rgb(255 255 255 / 10%));
83
+ -webkit-backdrop-filter: blur(.25px); backdrop-filter: blur(.25px);
84
+ box-shadow: var(--_opal-glass-rim);
85
+ transition: opacity 240ms ease;
86
+ }
87
+ .opal-slider-input:active:not(:disabled) ~ .opal-slider-thumb {
88
+ transform: scale(1.65); background: rgb(255 255 255 / 12%);
89
+ -webkit-backdrop-filter: blur(.5px) saturate(120%); backdrop-filter: blur(.5px) saturate(120%);
90
+ box-shadow: 0 7px 14px rgb(0 0 0 / 22%);
91
+ transition-duration: 170ms, 140ms, 170ms;
92
+ }
93
+ .opal-slider-input:active:not(:disabled) ~ .opal-slider-thumb::after { opacity: 1; transition-duration: 140ms; }
94
+ .opal-slider-input:focus-visible ~ .opal-slider-thumb { outline: 2px solid var(--opal-focus-color, #2885ff); outline-offset: 3px; }
95
+ .opal-slider:has(:disabled) { opacity: .4; }
96
+ .opal-slider-input:disabled { cursor: not-allowed; }
97
+ @media (prefers-reduced-motion: reduce) {
98
+ .opal-slider * { transition: none !important; }
99
+ .opal-slider-input:active:not(:disabled) ~ .opal-slider-thumb { transform: none; background: #fff; }
100
+ .opal-slider .opal-slider-thumb::after { display: none; }
101
+ .opal-slider .opal-slider-track { mask-image: none !important; -webkit-mask-image: none !important; }
102
+ }
103
+ @media (prefers-reduced-transparency: reduce) {
104
+ .opal-slider-input:active:not(:disabled) ~ .opal-slider-thumb { background: #fff; backdrop-filter: none; -webkit-backdrop-filter: none; }
105
+ .opal-slider .opal-slider-thumb::after { display: none; }
106
+ .opal-slider .opal-slider-track { mask-image: none !important; -webkit-mask-image: none !important; }
107
+ }
108
+ @media (forced-colors: active) {
109
+ .opal-slider-input { appearance: auto; -webkit-appearance: auto; opacity: 1; }
110
+ .opal-slider-track, .opal-slider-thumb { display: none; }
111
+ }
112
+
113
+ .opal-slider-optical-track { position:absolute; inset:-24px; pointer-events:none; }
114
+ .opal-slider-optical-track .opal-slider-track { left:24px; right:24px; width:calc(100% - 48px); top:43px; }
@@ -0,0 +1 @@
1
+ export default ".opal-slider-track, .opal-slider-thumb {\n position:absolute; pointer-events:none; box-sizing:border-box;\n --opal-slider-center:calc(18px + (100cqw - 36px) * var(--opal-slider-position));\n --opal-slider-fill:calc(18px + (100cqw - 36px) * var(--opal-slider-fraction));\n}\n.opal-slider {\n position: relative; display: inline-block; vertical-align: middle;\n width: 330px; max-width: 100%; height: 44px;\n container-type: inline-size;\n --opal-slider-position: var(--opal-slider-fraction);\n --opal-slider-direction: to right;\n}\n.opal-slider:dir(rtl) { --opal-slider-direction: to left; --opal-slider-position: calc(1 - var(--opal-slider-fraction)); }\n.opal-slider-input {\n appearance: none; -webkit-appearance: none; position: absolute; z-index: 3;\n inset: 0; width: 100%; height: 44px; margin: 0; padding: 0;\n opacity: 0; background: transparent; border: 0; cursor: pointer; touch-action: pan-y;\n}\n/* Retain native range interaction and its exact 36px thumb travel. */\n.opal-slider-input::-webkit-slider-runnable-track { height: 6px; }\n.opal-slider-input::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; width: 36px; height: 24px; margin-top: -9px; border: 0; }\n.opal-slider-input::-moz-range-track { height: 6px; }\n.opal-slider-input::-moz-range-thumb { width: 36px; height: 24px; border: 0; }\n.opal-slider-track {\n height: 6px; border-radius: 999px;\n background: var(--opal-slider-track, rgb(118 118 128 / 24%));\n}\n.opal-slider-track::before {\n content: ''; position: absolute; inset-block: 0; inset-inline-start: 0;\n width: var(--opal-slider-fill); border-radius: inherit;\n background: var(--opal-slider-tint, #009dff);\n}\n.opal-slider-track { top: 19px; width: 100%; }\n.opal-slider-thumb {\n top: 10px; left: calc(var(--opal-slider-center) - 18px);\n width: 36px; height: 24px; border-radius: 999px; background: #fff;\n box-shadow: 0 1px 4px rgb(0 0 0 / 14%), inset 0 0 0 .5px rgb(0 0 0 / 5%);\n transition: transform 380ms cubic-bezier(.22,.61,.36,1), background-color 240ms ease, box-shadow 300ms ease;\n}\n/* Put the glass surface above the reproduced track, so its pixels are\n softened and brightened too, rather than painted over the glass. */\n.opal-slider-thumb::after {\n content: ''; position: absolute; inset: 0; border-radius: inherit;\n pointer-events: none; opacity: 0;\n background: linear-gradient(to bottom, rgb(255 255 255 / 3%) 30%, rgb(255 255 255 / 10%));\n -webkit-backdrop-filter: blur(.25px); backdrop-filter: blur(.25px);\n box-shadow: var(--_opal-glass-rim);\n transition: opacity 240ms ease;\n}\n.opal-slider-input:active:not(:disabled) ~ .opal-slider-thumb {\n transform: scale(1.65); background: rgb(255 255 255 / 12%);\n -webkit-backdrop-filter: blur(.5px) saturate(120%); backdrop-filter: blur(.5px) saturate(120%);\n box-shadow: 0 7px 14px rgb(0 0 0 / 22%);\n transition-duration: 170ms, 140ms, 170ms;\n}\n.opal-slider-input:active:not(:disabled) ~ .opal-slider-thumb::after { opacity: 1; transition-duration: 140ms; }\n.opal-slider-input:focus-visible ~ .opal-slider-thumb { outline: 2px solid var(--opal-focus-color, #2885ff); outline-offset: 3px; }\n.opal-slider:has(:disabled) { opacity: .4; }\n.opal-slider-input:disabled { cursor: not-allowed; }\n@media (prefers-reduced-motion: reduce) {\n .opal-slider * { transition: none !important; }\n .opal-slider-input:active:not(:disabled) ~ .opal-slider-thumb { transform: none; background: #fff; }\n .opal-slider .opal-slider-thumb::after { display: none; }\n .opal-slider .opal-slider-track { mask-image: none !important; -webkit-mask-image: none !important; }\n}\n@media (prefers-reduced-transparency: reduce) {\n .opal-slider-input:active:not(:disabled) ~ .opal-slider-thumb { background: #fff; backdrop-filter: none; -webkit-backdrop-filter: none; }\n .opal-slider .opal-slider-thumb::after { display: none; }\n .opal-slider .opal-slider-track { mask-image: none !important; -webkit-mask-image: none !important; }\n}\n@media (forced-colors: active) {\n .opal-slider-input { appearance: auto; -webkit-appearance: auto; opacity: 1; }\n .opal-slider-track, .opal-slider-thumb { display: none; }\n}\n\n.opal-slider-optical-track { position:absolute; inset:-24px; pointer-events:none; }\n.opal-slider-optical-track .opal-slider-track { left:24px; right:24px; width:calc(100% - 48px); top:43px; }\n";
@@ -0,0 +1,17 @@
1
+ import { type ComponentPropsWithoutRef } from 'react';
2
+ export type SliderProps = Omit<ComponentPropsWithoutRef<'input'>, 'type' | 'children' | 'value' | 'defaultValue' | 'min' | 'max'> & {
3
+ value?: number;
4
+ defaultValue?: number;
5
+ min?: number;
6
+ max?: number;
7
+ tint?: `#${string}`;
8
+ onValueChange?: (value: number) => void;
9
+ };
10
+ export declare const Slider: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "type" | "value" | "defaultValue" | "children" | "max" | "min"> & {
11
+ value?: number;
12
+ defaultValue?: number;
13
+ min?: number;
14
+ max?: number;
15
+ tint?: `#${string}`;
16
+ onValueChange?: (value: number) => void;
17
+ } & import("react").RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,40 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
4
+ import { useGlassHeld, useGlassLens } from '../../internal/glass/lens.js';
5
+ import { materials } from '../../internal/glass/material.js';
6
+ import { stylesheetHref } from '../../internal/styles.js';
7
+ import componentCss from './slider.css.js';
8
+ import glassCss from '../../internal/glass/styles.js';
9
+ const css = `${glassCss}\n${componentCss}`;
10
+ const styleHref = stylesheetHref('slider', css);
11
+ export const Slider = forwardRef(function Slider({ value, defaultValue, min = 0, max = 100, step = 1, tint, className, style, onChange, onValueChange, ...props }, ref) {
12
+ const root = useRef(null);
13
+ const thumb = useRef(null);
14
+ const track = useRef(null);
15
+ const held = useGlassHeld(root);
16
+ const glass = useGlassLens(thumb, materials.thumb, { source: track, active: held && !props.disabled });
17
+ const input = useRef(null);
18
+ useImperativeHandle(ref, () => input.current, []);
19
+ const [internal, setInternal] = useState(defaultValue ?? (min + max) / 2);
20
+ const current = value ?? internal;
21
+ const progress = max > min ? Math.max(0, Math.min(100, (current - min) / (max - min) * 100)) : 0;
22
+ useEffect(() => {
23
+ const field = input.current;
24
+ if (field)
25
+ setInternal(field.valueAsNumber);
26
+ const form = field?.form;
27
+ const reset = () => queueMicrotask(() => { if (field)
28
+ setInternal(field.valueAsNumber); });
29
+ form?.addEventListener('reset', reset);
30
+ return () => form?.removeEventListener('reset', reset);
31
+ }, [min, max, step]);
32
+ const tintStyle = tint && /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i.test(tint) ? { '--opal-slider-tint': tint } : {};
33
+ return _jsxs(_Fragment, { children: [_jsx("style", { href: styleHref, precedence: "opalui", children: css }), glass.filter, _jsxs("span", { ref: root, className: ['opal-slider', className].filter(Boolean).join(' '), style: { '--opal-slider-progress': `${progress}%`, '--opal-slider-fraction': progress / 100, ...tintStyle, ...glass.surfaceStyle, ...style }, children: [_jsx("input", { ...props, ref: input, type: "range", min: min, max: max, step: step, value: value, defaultValue: defaultValue, className: "opal-slider-input", onChange: event => {
34
+ setInternal(event.currentTarget.valueAsNumber);
35
+ onChange?.(event);
36
+ if (!event.defaultPrevented)
37
+ onValueChange?.(event.currentTarget.valueAsNumber);
38
+ } }), _jsx("span", { ref: track, className: "opal-slider-optical-track", style: glass.sourceStyle, "aria-hidden": "true", children: _jsx("span", { className: "opal-slider-track" }) }), _jsx("span", { ref: thumb, className: "opal-slider-thumb", "aria-hidden": "true" })] })] });
39
+ });
40
+ //# sourceMappingURL=slider.js.map