@vielzeug/refine 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/dist/accordion-item.cjs +1 -1
  2. package/dist/accordion-item.cjs.map +1 -1
  3. package/dist/accordion-item.js +1 -1
  4. package/dist/accordion-item.js.map +1 -1
  5. package/dist/card.cjs +1 -1
  6. package/dist/card.cjs.map +1 -1
  7. package/dist/card.js +1 -1
  8. package/dist/card.js.map +1 -1
  9. package/dist/chat-message.cjs +1 -1
  10. package/dist/chat-message.cjs.map +1 -1
  11. package/dist/chat-message.js +1 -1
  12. package/dist/chat-message.js.map +1 -1
  13. package/dist/combobox.cjs +9 -7
  14. package/dist/combobox.cjs.map +1 -1
  15. package/dist/combobox.js +55 -48
  16. package/dist/combobox.js.map +1 -1
  17. package/dist/content/index.d.ts +2 -0
  18. package/dist/content/index.d.ts.map +1 -1
  19. package/dist/content/list/list-item.css.cjs +1 -1
  20. package/dist/content/list/list-item.css.cjs.map +1 -1
  21. package/dist/content/list/list-item.css.js +1 -1
  22. package/dist/content/list/list-item.css.js.map +1 -1
  23. package/dist/content/list/list-item.d.ts +9 -0
  24. package/dist/content/list/list-item.d.ts.map +1 -1
  25. package/dist/content/stats/stats.css.cjs +2 -0
  26. package/dist/content/stats/stats.css.cjs.map +1 -0
  27. package/dist/content/stats/stats.css.js +6 -0
  28. package/dist/content/stats/stats.css.js.map +1 -0
  29. package/dist/content/stats/stats.d.ts +72 -0
  30. package/dist/content/stats/stats.d.ts.map +1 -0
  31. package/dist/core/auto-resize.cjs +1 -1
  32. package/dist/core/auto-resize.cjs.map +1 -1
  33. package/dist/core/auto-resize.js +1 -1
  34. package/dist/core/auto-resize.js.map +1 -1
  35. package/dist/custom-elements.json +5087 -4791
  36. package/dist/datagrid.cjs +199 -179
  37. package/dist/datagrid.cjs.map +1 -1
  38. package/dist/datagrid.js +435 -321
  39. package/dist/datagrid.js.map +1 -1
  40. package/dist/disclosure/tab-item/tab-item.css.cjs +1 -1
  41. package/dist/disclosure/tab-item/tab-item.css.cjs.map +1 -1
  42. package/dist/disclosure/tab-item/tab-item.css.js +1 -1
  43. package/dist/disclosure/tab-item/tab-item.css.js.map +1 -1
  44. package/dist/disclosure/tab-item/tab-item.d.ts +3 -0
  45. package/dist/disclosure/tab-item/tab-item.d.ts.map +1 -1
  46. package/dist/disclosure/tabs/tabs.css.cjs +1 -1
  47. package/dist/disclosure/tabs/tabs.css.cjs.map +1 -1
  48. package/dist/disclosure/tabs/tabs.css.js +1 -1
  49. package/dist/disclosure/tabs/tabs.css.js.map +1 -1
  50. package/dist/disclosure/tabs/tabs.d.ts +4 -0
  51. package/dist/disclosure/tabs/tabs.d.ts.map +1 -1
  52. package/dist/frameworks/elements.d.ts +2 -1
  53. package/dist/icon.cjs +1 -1
  54. package/dist/icon.cjs.map +1 -1
  55. package/dist/icon.js +1 -1
  56. package/dist/icon.js.map +1 -1
  57. package/dist/input.cjs +5 -4
  58. package/dist/input.cjs.map +1 -1
  59. package/dist/input.js +14 -8
  60. package/dist/input.js.map +1 -1
  61. package/dist/inputs/combobox/combobox-options.cjs +1 -1
  62. package/dist/inputs/combobox/combobox-options.cjs.map +1 -1
  63. package/dist/inputs/combobox/combobox-options.d.ts.map +1 -1
  64. package/dist/inputs/combobox/combobox-options.js +1 -0
  65. package/dist/inputs/combobox/combobox-options.js.map +1 -1
  66. package/dist/inputs/combobox/combobox.css.cjs +1 -1
  67. package/dist/inputs/combobox/combobox.css.cjs.map +1 -1
  68. package/dist/inputs/combobox/combobox.css.js +1 -1
  69. package/dist/inputs/combobox/combobox.css.js.map +1 -1
  70. package/dist/inputs/combobox/combobox.d.ts +1 -0
  71. package/dist/inputs/combobox/combobox.d.ts.map +1 -1
  72. package/dist/inputs/combobox/combobox.types.d.ts +7 -0
  73. package/dist/inputs/combobox/combobox.types.d.ts.map +1 -1
  74. package/dist/inputs/datagrid/datagrid-model.cjs +1 -1
  75. package/dist/inputs/datagrid/datagrid-model.cjs.map +1 -1
  76. package/dist/inputs/datagrid/datagrid-model.d.ts +17 -3
  77. package/dist/inputs/datagrid/datagrid-model.d.ts.map +1 -1
  78. package/dist/inputs/datagrid/datagrid-model.js +93 -70
  79. package/dist/inputs/datagrid/datagrid-model.js.map +1 -1
  80. package/dist/inputs/datagrid/datagrid.css.cjs +1 -1
  81. package/dist/inputs/datagrid/datagrid.css.cjs.map +1 -1
  82. package/dist/inputs/datagrid/datagrid.css.js +1 -1
  83. package/dist/inputs/datagrid/datagrid.css.js.map +1 -1
  84. package/dist/inputs/datagrid/datagrid.d.ts +54 -4
  85. package/dist/inputs/datagrid/datagrid.d.ts.map +1 -1
  86. package/dist/inputs/index.d.ts +1 -1
  87. package/dist/inputs/index.d.ts.map +1 -1
  88. package/dist/inputs/input/input.css.cjs +1 -1
  89. package/dist/inputs/input/input.css.cjs.map +1 -1
  90. package/dist/inputs/input/input.css.js +1 -1
  91. package/dist/inputs/input/input.css.js.map +1 -1
  92. package/dist/inputs/input/input.d.ts +3 -0
  93. package/dist/inputs/input/input.d.ts.map +1 -1
  94. package/dist/inputs/select/select.css.cjs +1 -1
  95. package/dist/inputs/select/select.css.cjs.map +1 -1
  96. package/dist/inputs/select/select.css.js +1 -1
  97. package/dist/inputs/select/select.css.js.map +1 -1
  98. package/dist/inputs/select/select.d.ts +5 -0
  99. package/dist/inputs/select/select.d.ts.map +1 -1
  100. package/dist/layout/navbar/navbar.d.ts +2 -0
  101. package/dist/layout/navbar/navbar.d.ts.map +1 -1
  102. package/dist/layout/sidebar/sidebar.css.cjs +1 -1
  103. package/dist/layout/sidebar/sidebar.css.cjs.map +1 -1
  104. package/dist/layout/sidebar/sidebar.css.js +1 -1
  105. package/dist/layout/sidebar/sidebar.css.js.map +1 -1
  106. package/dist/layout/sidebar/sidebar.d.ts +8 -0
  107. package/dist/layout/sidebar/sidebar.d.ts.map +1 -1
  108. package/dist/list-item.cjs +6 -5
  109. package/dist/list-item.cjs.map +1 -1
  110. package/dist/list-item.js +23 -17
  111. package/dist/list-item.js.map +1 -1
  112. package/dist/list.cjs +1 -1
  113. package/dist/list.cjs.map +1 -1
  114. package/dist/list.js +1 -1
  115. package/dist/list.js.map +1 -1
  116. package/dist/menu.cjs +1 -1
  117. package/dist/menu.cjs.map +1 -1
  118. package/dist/menu.js +1 -1
  119. package/dist/menu.js.map +1 -1
  120. package/dist/navbar.cjs +2 -2
  121. package/dist/navbar.cjs.map +1 -1
  122. package/dist/navbar.js +7 -5
  123. package/dist/navbar.js.map +1 -1
  124. package/dist/navigation-menu.cjs +1 -1
  125. package/dist/navigation-menu.cjs.map +1 -1
  126. package/dist/navigation-menu.js +1 -1
  127. package/dist/navigation-menu.js.map +1 -1
  128. package/dist/overlay/popover/popover.css.cjs +1 -1
  129. package/dist/overlay/popover/popover.css.cjs.map +1 -1
  130. package/dist/overlay/popover/popover.css.js +1 -1
  131. package/dist/overlay/popover/popover.css.js.map +1 -1
  132. package/dist/overlay/popover/popover.d.ts +1 -0
  133. package/dist/overlay/popover/popover.d.ts.map +1 -1
  134. package/dist/overlay/shared/use-dialog.cjs +1 -1
  135. package/dist/overlay/shared/use-dialog.cjs.map +1 -1
  136. package/dist/overlay/shared/use-dialog.js +1 -1
  137. package/dist/overlay/shared/use-dialog.js.map +1 -1
  138. package/dist/overlay/shared/use-floating-trigger.cjs +1 -1
  139. package/dist/overlay/shared/use-floating-trigger.cjs.map +1 -1
  140. package/dist/overlay/shared/use-floating-trigger.js +1 -1
  141. package/dist/overlay/shared/use-floating-trigger.js.map +1 -1
  142. package/dist/popover.cjs.map +1 -1
  143. package/dist/popover.js.map +1 -1
  144. package/dist/radio.cjs +1 -1
  145. package/dist/radio.cjs.map +1 -1
  146. package/dist/radio.js +10 -8
  147. package/dist/radio.js.map +1 -1
  148. package/dist/rating.cjs +1 -1
  149. package/dist/rating.cjs.map +1 -1
  150. package/dist/rating.js +1 -1
  151. package/dist/rating.js.map +1 -1
  152. package/dist/refine.cjs +372 -323
  153. package/dist/refine.cjs.map +1 -1
  154. package/dist/refine.iife.js +372 -323
  155. package/dist/refine.iife.js.map +1 -1
  156. package/dist/refine.js +402 -353
  157. package/dist/refine.js.map +1 -1
  158. package/dist/select.cjs +16 -14
  159. package/dist/select.cjs.map +1 -1
  160. package/dist/select.js +118 -112
  161. package/dist/select.js.map +1 -1
  162. package/dist/sidebar.cjs +28 -23
  163. package/dist/sidebar.cjs.map +1 -1
  164. package/dist/sidebar.js +112 -77
  165. package/dist/sidebar.js.map +1 -1
  166. package/dist/slider.cjs +1 -1
  167. package/dist/slider.cjs.map +1 -1
  168. package/dist/slider.js +1 -1
  169. package/dist/slider.js.map +1 -1
  170. package/dist/stats.cjs +18 -0
  171. package/dist/stats.cjs.map +1 -0
  172. package/dist/stats.js +88 -0
  173. package/dist/stats.js.map +1 -0
  174. package/dist/stepper.cjs +1 -1
  175. package/dist/stepper.cjs.map +1 -1
  176. package/dist/stepper.js +1 -1
  177. package/dist/stepper.js.map +1 -1
  178. package/dist/styles/mixins/animation.css.cjs +2 -0
  179. package/dist/styles/mixins/animation.css.cjs.map +1 -1
  180. package/dist/styles/mixins/animation.css.d.ts.map +1 -1
  181. package/dist/styles/mixins/animation.css.js +2 -0
  182. package/dist/styles/mixins/animation.css.js.map +1 -1
  183. package/dist/tab-item.cjs +1 -1
  184. package/dist/tab-item.cjs.map +1 -1
  185. package/dist/tab-item.js +3 -2
  186. package/dist/tab-item.js.map +1 -1
  187. package/dist/tabs.cjs +1 -1
  188. package/dist/tabs.cjs.map +1 -1
  189. package/dist/tabs.js +3 -1
  190. package/dist/tabs.js.map +1 -1
  191. package/dist/toast.cjs.map +1 -1
  192. package/dist/toast.js.map +1 -1
  193. package/package.json +64 -56
@@ -1 +1 @@
1
- {"version":3,"file":"rating.cjs","names":[],"sources":["../src/inputs/rating/rating.ts"],"sourcesContent":["import { bind, createStableId, define, getHost, html, prop, useField } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { createErrorHelperState, createSliderControl } from '../../core';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport '../../content/icon/icon';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './rating.css?inline';\n\nexport type OreRatingEvents = {\n change: Event;\n input: Event;\n};\n\n/** Rating props */\nexport type OreRatingProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message — marks the field as invalid (fallback when the `error` slot is empty) */\n error?: string;\n /** Helper text displayed below the stars (fallback when the `helper` slot is empty) */\n helper?: string;\n /** Accessible group label */\n label?: string;\n /** Maximum rating (number of stars) */\n max?: number;\n /** Form field name */\n name?: string;\n /** Make rating read-only */\n readonly?: boolean;\n /** Component size */\n size?: ComponentSize;\n /** Render selected stars as solid-filled instead of outline-only */\n solid?: boolean;\n /** Current rating value */\n value?: number;\n};\n\n/**\n * A star rating input.\n *\n * @element ore-rating\n *\n * @attr {number} value - Current rating value (default: 0)\n * @attr {number} max - Maximum number of stars (default: 5)\n * @attr {boolean} readonly - Read-only display mode\n * @attr {boolean} disabled - Disabled state\n * @attr {string} label - aria-label for the group (default: 'Rating')\n * @attr {string} color - Theme color for filled stars: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} name - Form field name\n * @attr {boolean} solid - Fill selected stars (outline remains default when omitted)\n * @attr {string} helper - Helper text below the stars\n * @attr {string} error - Error message below the stars\n *\n * @fires input - Emitted when the rating changes.\n * @fires change - Emitted when the rating changes.\n *\n * @cssprop --rating-star-size - Star diameter\n * @cssprop --rating-color-empty - Empty star color\n * @cssprop --rating-color-filled - Filled star color\n * @cssprop --rating-gap - Gap between stars\n *\n * @part stars - Stars container.\n * @part star - Star item element.\n * @part helper-text - The helper/error text element.\n * @example\n * ```html\n * <ore-rating value=\"3\" max=\"5\" color=\"warning\"></ore-rating>\n * <ore-rating value=\"4\" solid></ore-rating>\n * ```\n */\nexport const RATING_TAG = 'ore-rating' as const;\ndefine<OreRatingProps>(RATING_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string('Rating'),\n max: prop.number(5),\n name: prop.string(),\n readonly: prop.bool(false),\n solid: prop.bool(false),\n value: prop.number(0),\n },\n setup(props) {\n const el = getHost();\n const normalizedValue = computed(() => {\n const max = Math.max(1, Number(props.max?.value) || 5);\n const raw = Number(props.value?.value);\n const safe = Number.isFinite(raw) ? raw : 0;\n\n return Math.min(max, Math.max(0, safe));\n });\n\n const isDisabled = computed(() => Boolean(props.disabled.value));\n\n defineFieldValue(\n el,\n () => String(normalizedValue.value),\n (value) => {\n el.setAttribute('value', value);\n },\n );\n\n useField({\n disabled: isDisabled,\n value: computed(() => String(normalizedValue.value || 0)),\n });\n\n const assistiveId = createStableId('helper');\n const assistive = createErrorHelperState({ error: props.error, helper: props.helper });\n const errorText = computed(() => assistive.value.errorText);\n const helperText = computed(() => assistive.value.helperText);\n const ariaDescribedBy = computed(() => (errorText.value || helperText.value ? assistiveId : null));\n\n const isInteractive = computed(() => !props.readonly?.value && !isDisabled.value);\n const hovered = signal<number | null>(null);\n const displayValue = computed(() => hovered.value ?? normalizedValue.value);\n const getStarButtons = () => {\n return [...(el.shadowRoot?.querySelectorAll<HTMLButtonElement>('[data-star]') ?? [])];\n };\n const ratingControl = createSliderControl({\n max: computed(() => Number(props.max?.value) || 5),\n min: signal(1),\n step: signal(1),\n });\n\n function spawnSparkles(star: number) {\n const layer = el.shadowRoot?.querySelector<HTMLElement>('.sparkle-layer');\n const btn = el.shadowRoot?.querySelector<HTMLElement>(`[data-star=\"${star}\"]`);\n\n if (!layer || !btn) return;\n\n const cx = btn.offsetLeft + btn.offsetWidth / 2;\n const cy = btn.offsetTop + btn.offsetHeight / 2;\n const count = 10;\n\n for (let i = 0; i < count; i++) {\n const p = document.createElement('span');\n const angle = (360 / count) * i + (Math.random() * 30 - 15);\n const dist = 18 + Math.random() * 20;\n const size = 3 + Math.random() * 4;\n const dur = 380 + Math.random() * 220;\n\n p.className = 'sparkle';\n p.style.cssText = [\n `left:${cx}px`,\n `top:${cy}px`,\n `--_angle:${angle}deg`,\n `--_dist:${dist}px`,\n `width:${size}px`,\n `height:${size}px`,\n `--_dur:${dur}ms`,\n `animation-delay:${Math.random() * 60}ms`,\n ].join(';');\n layer.appendChild(p);\n p.addEventListener('animationend', () => p.remove(), { once: true });\n }\n }\n function select(star: number, _originalEvent?: Event) {\n if (!isInteractive.value) return;\n\n const max = Math.max(1, Number(props.max?.value) || 5);\n const nextValue = Math.min(max, Math.max(0, star));\n\n if (nextValue === normalizedValue.value) return;\n\n setFieldValue(el, String(nextValue));\n dispatchNativeFieldEvent(el, 'input');\n dispatchNativeFieldEvent(el, 'change');\n spawnSparkles(nextValue);\n }\n function handleKeydown(e: KeyboardEvent, star: number) {\n const next = ratingControl.nextFromKey(e.key, star);\n\n if (next == null) return;\n\n e.preventDefault();\n select(next, e);\n\n const buttons = getStarButtons();\n\n buttons[next - 1]?.focus();\n }\n\n const stars = computed(() => {\n const max = Number(props.max?.value) || 5;\n\n return Array.from({ length: max }, (_, i) => i + 1);\n });\n\n bind({ attr: { size: props.size } });\n\n return html`\n <div\n class=\"stars\"\n part=\"stars\"\n role=\"radiogroup\"\n aria-label=\"${props.label}\"\n aria-describedby=\"${ariaDescribedBy}\">\n ${() =>\n stars.value.map(\n (star) => html`\n <button\n class=\"star-btn\"\n part=\"star\"\n type=\"button\"\n role=\"radio\"\n aria-label=\"${() => `${star} ${star === 1 ? 'star' : 'stars'}`}\"\n aria-checked=\"${() => String(star === normalizedValue.value)}\"\n data-star=\"${star}\"\n ?data-filled=\"${() => star <= displayValue.value}\"\n disabled=\"${() => (!isInteractive.value ? true : null)}\"\n @click=\"${(e: Event) => select(star, e)}\"\n @pointerenter=\"${() => {\n if (isInteractive.value) hovered.value = star;\n }}\"\n @pointerleave=\"${() => {\n hovered.value = null;\n }}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, star)}\">\n <ore-icon name=\"star\" size=\"var(--_star-size)\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n `,\n )}\n <div class=\"sparkle-layer\"></div>\n </div>\n ${renderHelperRegion(assistiveId, errorText, helperText)}\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin({}), coarsePointerMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"rating.cjs","names":[],"sources":["../src/inputs/rating/rating.ts"],"sourcesContent":["import { bind, createStableId, define, getHost, html, prop, useField } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { createErrorHelperState, createSliderControl } from '../../core';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport '../../content/icon/icon';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './rating.css?inline';\n\nexport type OreRatingEvents = {\n change: Event;\n input: Event;\n};\n\n/** Rating props */\nexport type OreRatingProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message — marks the field as invalid (fallback when the `error` slot is empty) */\n error?: string;\n /** Helper text displayed below the stars (fallback when the `helper` slot is empty) */\n helper?: string;\n /** Accessible group label */\n label?: string;\n /** Maximum rating (number of stars) */\n max?: number;\n /** Form field name */\n name?: string;\n /** Make rating read-only */\n readonly?: boolean;\n /** Component size */\n size?: ComponentSize;\n /** Render selected stars as solid-filled instead of outline-only */\n solid?: boolean;\n /** Current rating value */\n value?: number;\n};\n\n/**\n * A star rating input.\n *\n * @element ore-rating\n *\n * @attr {number} value - Current rating value (default: 0)\n * @attr {number} max - Maximum number of stars (default: 5)\n * @attr {boolean} readonly - Read-only display mode\n * @attr {boolean} disabled - Disabled state\n * @attr {string} label - aria-label for the group (default: 'Rating')\n * @attr {string} color - Theme color for filled stars: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} name - Form field name\n * @attr {boolean} solid - Fill selected stars (outline remains default when omitted)\n * @attr {string} helper - Helper text below the stars\n * @attr {string} error - Error message below the stars\n *\n * @fires input - Emitted when the rating changes.\n * @fires change - Emitted when the rating changes.\n *\n * @cssprop --rating-star-size - Star diameter\n * @cssprop --rating-color-empty - Empty star color\n * @cssprop --rating-color-filled - Filled star color\n * @cssprop --rating-gap - Gap between stars\n *\n * @part stars - Stars container.\n * @part star - Star item element.\n * @part helper-text - The helper/error text element.\n * @example\n * ```html\n * <ore-rating value=\"3\" max=\"5\" color=\"warning\"></ore-rating>\n * <ore-rating value=\"4\" solid></ore-rating>\n * ```\n */\nexport const RATING_TAG = 'ore-rating' as const;\ndefine<OreRatingProps>(RATING_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string('Rating'),\n max: prop.number(5),\n name: prop.string(),\n readonly: prop.bool(false),\n solid: prop.bool(false),\n value: prop.number(0),\n },\n setup(props) {\n const el = getHost();\n const normalizedValue = computed(() => {\n const max = Math.max(1, Number(props.max?.value) || 5);\n const raw = Number(props.value?.value);\n const safe = Number.isFinite(raw) ? raw : 0;\n\n return Math.min(max, Math.max(0, safe));\n });\n\n const isDisabled = computed(() => Boolean(props.disabled.value));\n\n defineFieldValue(\n el,\n () => String(normalizedValue.value),\n (value) => {\n el.setAttribute('value', value);\n },\n );\n\n useField({\n disabled: isDisabled,\n value: computed(() => String(normalizedValue.value || 0)),\n });\n\n const assistiveId = createStableId('helper');\n const assistive = createErrorHelperState({ error: props.error, helper: props.helper });\n const errorText = computed(() => assistive.value.errorText);\n const helperText = computed(() => assistive.value.helperText);\n const ariaDescribedBy = computed(() => (errorText.value || helperText.value ? assistiveId : null));\n\n const isInteractive = computed(() => !props.readonly?.value && !isDisabled.value);\n const hovered = signal<number | null>(null);\n const displayValue = computed(() => hovered.value ?? normalizedValue.value);\n const getStarButtons = () => {\n return [...(el.shadowRoot?.querySelectorAll<HTMLButtonElement>('[data-star]') ?? [])];\n };\n const ratingControl = createSliderControl({\n max: computed(() => Number(props.max?.value) || 5),\n min: signal(1),\n step: signal(1),\n });\n\n function spawnSparkles(star: number) {\n const layer = el.shadowRoot?.querySelector<HTMLElement>('.sparkle-layer');\n const btn = el.shadowRoot?.querySelector<HTMLElement>(`[data-star=\"${star}\"]`);\n\n if (!layer || !btn) return;\n\n const cx = btn.offsetLeft + btn.offsetWidth / 2;\n const cy = btn.offsetTop + btn.offsetHeight / 2;\n const count = 10;\n\n for (let i = 0; i < count; i++) {\n const p = document.createElement('span');\n const angle = (360 / count) * i + (Math.random() * 30 - 15);\n const dist = 18 + Math.random() * 20;\n const size = 3 + Math.random() * 4;\n const dur = 380 + Math.random() * 220;\n\n p.className = 'sparkle';\n p.style.cssText = [\n `left:${cx}px`,\n `top:${cy}px`,\n `--_angle:${angle}deg`,\n `--_dist:${dist}px`,\n `width:${size}px`,\n `height:${size}px`,\n `--_dur:${dur}ms`,\n `animation-delay:${Math.random() * 60}ms`,\n ].join(';');\n layer.appendChild(p);\n p.addEventListener('animationend', () => p.remove(), { once: true });\n }\n }\n function select(star: number, _originalEvent?: Event) {\n if (!isInteractive.value) return;\n\n const max = Math.max(1, Number(props.max?.value) || 5);\n const nextValue = Math.min(max, Math.max(0, star));\n\n if (nextValue === normalizedValue.value) return;\n\n setFieldValue(el, String(nextValue));\n dispatchNativeFieldEvent(el, 'input');\n dispatchNativeFieldEvent(el, 'change');\n spawnSparkles(nextValue);\n }\n function handleKeydown(e: KeyboardEvent, star: number) {\n const next = ratingControl.nextFromKey(e.key, star);\n\n if (next == null) return;\n\n e.preventDefault();\n select(next, e);\n\n const buttons = getStarButtons();\n\n buttons[next - 1]?.focus();\n }\n\n const stars = computed(() => {\n const max = Number(props.max?.value) || 5;\n\n return Array.from({ length: max }, (_, i) => i + 1);\n });\n\n bind({ attr: { size: props.size } });\n\n return html`\n <div\n class=\"stars\"\n part=\"stars\"\n role=\"radiogroup\"\n aria-label=\"${props.label}\"\n aria-describedby=\"${ariaDescribedBy}\">\n ${() =>\n stars.value.map(\n (star) => html`\n <button\n class=\"star-btn\"\n part=\"star\"\n type=\"button\"\n role=\"radio\"\n aria-label=\"${() => `${star} ${star === 1 ? 'star' : 'stars'}`}\"\n aria-checked=\"${() => String(star === normalizedValue.value)}\"\n data-star=\"${star}\"\n ?data-filled=\"${() => star <= displayValue.value}\"\n disabled=\"${() => (!isInteractive.value ? true : null)}\"\n @click=\"${(e: Event) => select(star, e)}\"\n @pointerenter=\"${() => {\n if (isInteractive.value) hovered.value = star;\n }}\"\n @pointerleave=\"${() => {\n hovered.value = null;\n }}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, star)}\">\n <ore-icon name=\"star\" size=\"var(--_star-size)\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n `,\n )}\n <div class=\"sparkle-layer\"></div>\n </div>\n ${renderHelperRegion(assistiveId, errorText, helperText)}\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin({}), coarsePointerMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"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"}
package/dist/rating.js CHANGED
@@ -50,7 +50,7 @@ g(C, {
50
50
  if (!n || !r) return;
51
51
  let i = r.offsetLeft + r.offsetWidth / 2, a = r.offsetTop + r.offsetHeight / 2;
52
52
  for (let e = 0; e < 10; e++) {
53
- let t = document.createElement("span"), r = 360 / 10 * e + (Math.random() * 30 - 15), o = 18 + Math.random() * 20, s = 3 + Math.random() * 4, c = 380 + Math.random() * 220;
53
+ let t = document.createElement("span"), r = 36 * e + (Math.random() * 30 - 15), o = 18 + Math.random() * 20, s = 3 + Math.random() * 4, c = 380 + Math.random() * 220;
54
54
  t.className = "sparkle", t.style.cssText = [
55
55
  `left:${i}px`,
56
56
  `top:${a}px`,
@@ -1 +1 @@
1
- {"version":3,"file":"rating.js","names":[],"sources":["../src/inputs/rating/rating.ts"],"sourcesContent":["import { bind, createStableId, define, getHost, html, prop, useField } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { createErrorHelperState, createSliderControl } from '../../core';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport '../../content/icon/icon';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './rating.css?inline';\n\nexport type OreRatingEvents = {\n change: Event;\n input: Event;\n};\n\n/** Rating props */\nexport type OreRatingProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message — marks the field as invalid (fallback when the `error` slot is empty) */\n error?: string;\n /** Helper text displayed below the stars (fallback when the `helper` slot is empty) */\n helper?: string;\n /** Accessible group label */\n label?: string;\n /** Maximum rating (number of stars) */\n max?: number;\n /** Form field name */\n name?: string;\n /** Make rating read-only */\n readonly?: boolean;\n /** Component size */\n size?: ComponentSize;\n /** Render selected stars as solid-filled instead of outline-only */\n solid?: boolean;\n /** Current rating value */\n value?: number;\n};\n\n/**\n * A star rating input.\n *\n * @element ore-rating\n *\n * @attr {number} value - Current rating value (default: 0)\n * @attr {number} max - Maximum number of stars (default: 5)\n * @attr {boolean} readonly - Read-only display mode\n * @attr {boolean} disabled - Disabled state\n * @attr {string} label - aria-label for the group (default: 'Rating')\n * @attr {string} color - Theme color for filled stars: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} name - Form field name\n * @attr {boolean} solid - Fill selected stars (outline remains default when omitted)\n * @attr {string} helper - Helper text below the stars\n * @attr {string} error - Error message below the stars\n *\n * @fires input - Emitted when the rating changes.\n * @fires change - Emitted when the rating changes.\n *\n * @cssprop --rating-star-size - Star diameter\n * @cssprop --rating-color-empty - Empty star color\n * @cssprop --rating-color-filled - Filled star color\n * @cssprop --rating-gap - Gap between stars\n *\n * @part stars - Stars container.\n * @part star - Star item element.\n * @part helper-text - The helper/error text element.\n * @example\n * ```html\n * <ore-rating value=\"3\" max=\"5\" color=\"warning\"></ore-rating>\n * <ore-rating value=\"4\" solid></ore-rating>\n * ```\n */\nexport const RATING_TAG = 'ore-rating' as const;\ndefine<OreRatingProps>(RATING_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string('Rating'),\n max: prop.number(5),\n name: prop.string(),\n readonly: prop.bool(false),\n solid: prop.bool(false),\n value: prop.number(0),\n },\n setup(props) {\n const el = getHost();\n const normalizedValue = computed(() => {\n const max = Math.max(1, Number(props.max?.value) || 5);\n const raw = Number(props.value?.value);\n const safe = Number.isFinite(raw) ? raw : 0;\n\n return Math.min(max, Math.max(0, safe));\n });\n\n const isDisabled = computed(() => Boolean(props.disabled.value));\n\n defineFieldValue(\n el,\n () => String(normalizedValue.value),\n (value) => {\n el.setAttribute('value', value);\n },\n );\n\n useField({\n disabled: isDisabled,\n value: computed(() => String(normalizedValue.value || 0)),\n });\n\n const assistiveId = createStableId('helper');\n const assistive = createErrorHelperState({ error: props.error, helper: props.helper });\n const errorText = computed(() => assistive.value.errorText);\n const helperText = computed(() => assistive.value.helperText);\n const ariaDescribedBy = computed(() => (errorText.value || helperText.value ? assistiveId : null));\n\n const isInteractive = computed(() => !props.readonly?.value && !isDisabled.value);\n const hovered = signal<number | null>(null);\n const displayValue = computed(() => hovered.value ?? normalizedValue.value);\n const getStarButtons = () => {\n return [...(el.shadowRoot?.querySelectorAll<HTMLButtonElement>('[data-star]') ?? [])];\n };\n const ratingControl = createSliderControl({\n max: computed(() => Number(props.max?.value) || 5),\n min: signal(1),\n step: signal(1),\n });\n\n function spawnSparkles(star: number) {\n const layer = el.shadowRoot?.querySelector<HTMLElement>('.sparkle-layer');\n const btn = el.shadowRoot?.querySelector<HTMLElement>(`[data-star=\"${star}\"]`);\n\n if (!layer || !btn) return;\n\n const cx = btn.offsetLeft + btn.offsetWidth / 2;\n const cy = btn.offsetTop + btn.offsetHeight / 2;\n const count = 10;\n\n for (let i = 0; i < count; i++) {\n const p = document.createElement('span');\n const angle = (360 / count) * i + (Math.random() * 30 - 15);\n const dist = 18 + Math.random() * 20;\n const size = 3 + Math.random() * 4;\n const dur = 380 + Math.random() * 220;\n\n p.className = 'sparkle';\n p.style.cssText = [\n `left:${cx}px`,\n `top:${cy}px`,\n `--_angle:${angle}deg`,\n `--_dist:${dist}px`,\n `width:${size}px`,\n `height:${size}px`,\n `--_dur:${dur}ms`,\n `animation-delay:${Math.random() * 60}ms`,\n ].join(';');\n layer.appendChild(p);\n p.addEventListener('animationend', () => p.remove(), { once: true });\n }\n }\n function select(star: number, _originalEvent?: Event) {\n if (!isInteractive.value) return;\n\n const max = Math.max(1, Number(props.max?.value) || 5);\n const nextValue = Math.min(max, Math.max(0, star));\n\n if (nextValue === normalizedValue.value) return;\n\n setFieldValue(el, String(nextValue));\n dispatchNativeFieldEvent(el, 'input');\n dispatchNativeFieldEvent(el, 'change');\n spawnSparkles(nextValue);\n }\n function handleKeydown(e: KeyboardEvent, star: number) {\n const next = ratingControl.nextFromKey(e.key, star);\n\n if (next == null) return;\n\n e.preventDefault();\n select(next, e);\n\n const buttons = getStarButtons();\n\n buttons[next - 1]?.focus();\n }\n\n const stars = computed(() => {\n const max = Number(props.max?.value) || 5;\n\n return Array.from({ length: max }, (_, i) => i + 1);\n });\n\n bind({ attr: { size: props.size } });\n\n return html`\n <div\n class=\"stars\"\n part=\"stars\"\n role=\"radiogroup\"\n aria-label=\"${props.label}\"\n aria-describedby=\"${ariaDescribedBy}\">\n ${() =>\n stars.value.map(\n (star) => html`\n <button\n class=\"star-btn\"\n part=\"star\"\n type=\"button\"\n role=\"radio\"\n aria-label=\"${() => `${star} ${star === 1 ? 'star' : 'stars'}`}\"\n aria-checked=\"${() => String(star === normalizedValue.value)}\"\n data-star=\"${star}\"\n ?data-filled=\"${() => star <= displayValue.value}\"\n disabled=\"${() => (!isInteractive.value ? true : null)}\"\n @click=\"${(e: Event) => select(star, e)}\"\n @pointerenter=\"${() => {\n if (isInteractive.value) hovered.value = star;\n }}\"\n @pointerleave=\"${() => {\n hovered.value = null;\n }}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, star)}\">\n <ore-icon name=\"star\" size=\"var(--_star-size)\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n `,\n )}\n <div class=\"sparkle-layer\"></div>\n </div>\n ${renderHelperRegion(assistiveId, errorText, helperText)}\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin({}), coarsePointerMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":";;;;;;;;;;;;AA4EA,IAAa,IAAa;AAC1B,EAAuB,GAAY;CACjC,gBAAgB;CAChB,OAAO;EACL,GAAG;EACH,GAAG;EACH,GAAG;EACH,OAAO,EAAK,OAAO;EACnB,QAAQ,EAAK,OAAO;EACpB,OAAO,EAAK,OAAO,QAAQ;EAC3B,KAAK,EAAK,OAAO,CAAC;EAClB,MAAM,EAAK,OAAO;EAClB,UAAU,EAAK,KAAK,EAAK;EACzB,OAAO,EAAK,KAAK,EAAK;EACtB,OAAO,EAAK,OAAO,CAAC;CACtB;CACA,MAAM,GAAO;EACX,IAAM,IAAK,EAAQ,GACb,IAAkB,QAAe;GACrC,IAAM,IAAM,KAAK,IAAI,GAAG,OAAO,EAAM,KAAK,KAAK,KAAK,CAAC,GAC/C,IAAM,OAAO,EAAM,OAAO,KAAK;GAGrC,OAAO,KAAK,IAAI,GAAK,KAAK,IAAI,GAFjB,OAAO,SAAS,CAAG,IAAI,IAAM,CAEL,CAAC;EACxC,CAAC,GAEK,IAAa,QAAe,EAAQ,EAAM,SAAS,KAAM;EAU/D,AARA,EACE,SACM,OAAO,EAAgB,KAAK,IACjC,MAAU;GACT,EAAG,aAAa,SAAS,CAAK;EAChC,CACF,GAEA,EAAS;GACP,UAAU;GACV,OAAO,QAAe,OAAO,EAAgB,SAAS,CAAC,CAAC;EAC1D,CAAC;EAED,IAAM,IAAc,EAAe,QAAQ,GACrC,IAAY,EAAuB;GAAE,OAAO,EAAM;GAAO,QAAQ,EAAM;EAAO,CAAC,GAC/E,IAAY,QAAe,EAAU,MAAM,SAAS,GACpD,IAAa,QAAe,EAAU,MAAM,UAAU,GACtD,IAAkB,QAAgB,EAAU,SAAS,EAAW,QAAQ,IAAc,IAAK,GAE3F,IAAgB,QAAe,CAAC,EAAM,UAAU,SAAS,CAAC,EAAW,KAAK,GAC1E,IAAU,EAAsB,IAAI,GACpC,IAAe,QAAe,EAAQ,SAAS,EAAgB,KAAK,GACpE,UACG,CAAC,GAAI,EAAG,YAAY,iBAAoC,aAAa,KAAK,CAAC,CAAE,GAEhF,IAAgB,EAAoB;GACxC,KAAK,QAAe,OAAO,EAAM,KAAK,KAAK,KAAK,CAAC;GACjD,KAAK,EAAO,CAAC;GACb,MAAM,EAAO,CAAC;EAChB,CAAC;EAED,SAAS,EAAc,GAAc;GACnC,IAAM,IAAQ,EAAG,YAAY,cAA2B,gBAAgB,GAClE,IAAM,EAAG,YAAY,cAA2B,eAAe,EAAK,GAAG;GAE7E,IAAI,CAAC,KAAS,CAAC,GAAK;GAEpB,IAAM,IAAK,EAAI,aAAa,EAAI,cAAc,GACxC,IAAK,EAAI,YAAY,EAAI,eAAe;GAG9C,KAAK,IAAI,IAAI,GAAG,IAAI,IAAO,KAAK;IAC9B,IAAM,IAAI,SAAS,cAAc,MAAM,GACjC,IAAS,MAAM,KAAS,KAAK,KAAK,OAAO,IAAI,KAAK,KAClD,IAAO,KAAK,KAAK,OAAO,IAAI,IAC5B,IAAO,IAAI,KAAK,OAAO,IAAI,GAC3B,IAAM,MAAM,KAAK,OAAO,IAAI;IAclC,AAZA,EAAE,YAAY,WACd,EAAE,MAAM,UAAU;KAChB,QAAQ,EAAG;KACX,OAAO,EAAG;KACV,YAAY,EAAM;KAClB,WAAW,EAAK;KAChB,SAAS,EAAK;KACd,UAAU,EAAK;KACf,UAAU,EAAI;KACd,mBAAmB,KAAK,OAAO,IAAI,GAAG;IACxC,CAAC,CAAC,KAAK,GAAG,GACV,EAAM,YAAY,CAAC,GACnB,EAAE,iBAAiB,sBAAsB,EAAE,OAAO,GAAG,EAAE,MAAM,GAAK,CAAC;GACrE;EACF;EACA,SAAS,EAAO,GAAc,GAAwB;GACpD,IAAI,CAAC,EAAc,OAAO;GAE1B,IAAM,IAAM,KAAK,IAAI,GAAG,OAAO,EAAM,KAAK,KAAK,KAAK,CAAC,GAC/C,IAAY,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,CAAI,CAAC;GAE7C,MAAc,EAAgB,UAElC,EAAc,GAAI,OAAO,CAAS,CAAC,GACnC,EAAyB,GAAI,OAAO,GACpC,EAAyB,GAAI,QAAQ,GACrC,EAAc,CAAS;EACzB;EACA,SAAS,EAAc,GAAkB,GAAc;GACrD,IAAM,IAAO,EAAc,YAAY,EAAE,KAAK,CAAI;GAE9C,KAAQ,SAEZ,EAAE,eAAe,GACjB,EAAO,GAAM,CAAC,GAId,EAAA,CAAA,CAAQ,IAAO,EAAE,EAAE,MAAM;EAC3B;EAEA,IAAM,IAAQ,QAAe;GAC3B,IAAM,IAAM,OAAO,EAAM,KAAK,KAAK,KAAK;GAExC,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAI,IAAI,GAAG,MAAM,IAAI,CAAC;EACpD,CAAC;EAID,OAFA,EAAK,EAAE,MAAM,EAAE,MAAM,EAAM,KAAK,EAAE,CAAC,GAE5B,CAAI;;;;;sBAKO,EAAM,MAAM;4BACN,EAAgB;gBAElC,EAAM,MAAM,KACT,MAAS,CAAI;;;;;;oCAMU,GAAG,EAAK,GAAG,MAAS,IAAI,SAAS,UAAU;sCACzC,OAAO,MAAS,EAAgB,KAAK,EAAE;6BAChD,EAAK;sCACI,KAAQ,EAAa,MAAM;kCAC9B,CAAC,EAAc,SAAe,KAAM;2BAC5C,MAAa,EAAO,GAAM,CAAC,EAAE;uCACjB;GACrB,AAAI,EAAc,UAAO,EAAQ,QAAQ;EAC3C,EAAE;uCACqB;GACrB,EAAQ,QAAQ;EAClB,EAAE;6BACW,MAAqB,EAAc,GAAG,CAAI,EAAE;;;aAI/D,EAAE;;;QAGJ,EAAmB,GAAa,GAAW,CAAU,EAAE;;CAE7D;CACA,QAAQ;EAAC;EAAiB,EAAiB,CAAC,CAAC;EAAG;EAAoB;EAAoB;CAAe;AACzG,CAAC"}
1
+ {"version":3,"file":"rating.js","names":[],"sources":["../src/inputs/rating/rating.ts"],"sourcesContent":["import { bind, createStableId, define, getHost, html, prop, useField } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { createErrorHelperState, createSliderControl } from '../../core';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport '../../content/icon/icon';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './rating.css?inline';\n\nexport type OreRatingEvents = {\n change: Event;\n input: Event;\n};\n\n/** Rating props */\nexport type OreRatingProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message — marks the field as invalid (fallback when the `error` slot is empty) */\n error?: string;\n /** Helper text displayed below the stars (fallback when the `helper` slot is empty) */\n helper?: string;\n /** Accessible group label */\n label?: string;\n /** Maximum rating (number of stars) */\n max?: number;\n /** Form field name */\n name?: string;\n /** Make rating read-only */\n readonly?: boolean;\n /** Component size */\n size?: ComponentSize;\n /** Render selected stars as solid-filled instead of outline-only */\n solid?: boolean;\n /** Current rating value */\n value?: number;\n};\n\n/**\n * A star rating input.\n *\n * @element ore-rating\n *\n * @attr {number} value - Current rating value (default: 0)\n * @attr {number} max - Maximum number of stars (default: 5)\n * @attr {boolean} readonly - Read-only display mode\n * @attr {boolean} disabled - Disabled state\n * @attr {string} label - aria-label for the group (default: 'Rating')\n * @attr {string} color - Theme color for filled stars: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} name - Form field name\n * @attr {boolean} solid - Fill selected stars (outline remains default when omitted)\n * @attr {string} helper - Helper text below the stars\n * @attr {string} error - Error message below the stars\n *\n * @fires input - Emitted when the rating changes.\n * @fires change - Emitted when the rating changes.\n *\n * @cssprop --rating-star-size - Star diameter\n * @cssprop --rating-color-empty - Empty star color\n * @cssprop --rating-color-filled - Filled star color\n * @cssprop --rating-gap - Gap between stars\n *\n * @part stars - Stars container.\n * @part star - Star item element.\n * @part helper-text - The helper/error text element.\n * @example\n * ```html\n * <ore-rating value=\"3\" max=\"5\" color=\"warning\"></ore-rating>\n * <ore-rating value=\"4\" solid></ore-rating>\n * ```\n */\nexport const RATING_TAG = 'ore-rating' as const;\ndefine<OreRatingProps>(RATING_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string('Rating'),\n max: prop.number(5),\n name: prop.string(),\n readonly: prop.bool(false),\n solid: prop.bool(false),\n value: prop.number(0),\n },\n setup(props) {\n const el = getHost();\n const normalizedValue = computed(() => {\n const max = Math.max(1, Number(props.max?.value) || 5);\n const raw = Number(props.value?.value);\n const safe = Number.isFinite(raw) ? raw : 0;\n\n return Math.min(max, Math.max(0, safe));\n });\n\n const isDisabled = computed(() => Boolean(props.disabled.value));\n\n defineFieldValue(\n el,\n () => String(normalizedValue.value),\n (value) => {\n el.setAttribute('value', value);\n },\n );\n\n useField({\n disabled: isDisabled,\n value: computed(() => String(normalizedValue.value || 0)),\n });\n\n const assistiveId = createStableId('helper');\n const assistive = createErrorHelperState({ error: props.error, helper: props.helper });\n const errorText = computed(() => assistive.value.errorText);\n const helperText = computed(() => assistive.value.helperText);\n const ariaDescribedBy = computed(() => (errorText.value || helperText.value ? assistiveId : null));\n\n const isInteractive = computed(() => !props.readonly?.value && !isDisabled.value);\n const hovered = signal<number | null>(null);\n const displayValue = computed(() => hovered.value ?? normalizedValue.value);\n const getStarButtons = () => {\n return [...(el.shadowRoot?.querySelectorAll<HTMLButtonElement>('[data-star]') ?? [])];\n };\n const ratingControl = createSliderControl({\n max: computed(() => Number(props.max?.value) || 5),\n min: signal(1),\n step: signal(1),\n });\n\n function spawnSparkles(star: number) {\n const layer = el.shadowRoot?.querySelector<HTMLElement>('.sparkle-layer');\n const btn = el.shadowRoot?.querySelector<HTMLElement>(`[data-star=\"${star}\"]`);\n\n if (!layer || !btn) return;\n\n const cx = btn.offsetLeft + btn.offsetWidth / 2;\n const cy = btn.offsetTop + btn.offsetHeight / 2;\n const count = 10;\n\n for (let i = 0; i < count; i++) {\n const p = document.createElement('span');\n const angle = (360 / count) * i + (Math.random() * 30 - 15);\n const dist = 18 + Math.random() * 20;\n const size = 3 + Math.random() * 4;\n const dur = 380 + Math.random() * 220;\n\n p.className = 'sparkle';\n p.style.cssText = [\n `left:${cx}px`,\n `top:${cy}px`,\n `--_angle:${angle}deg`,\n `--_dist:${dist}px`,\n `width:${size}px`,\n `height:${size}px`,\n `--_dur:${dur}ms`,\n `animation-delay:${Math.random() * 60}ms`,\n ].join(';');\n layer.appendChild(p);\n p.addEventListener('animationend', () => p.remove(), { once: true });\n }\n }\n function select(star: number, _originalEvent?: Event) {\n if (!isInteractive.value) return;\n\n const max = Math.max(1, Number(props.max?.value) || 5);\n const nextValue = Math.min(max, Math.max(0, star));\n\n if (nextValue === normalizedValue.value) return;\n\n setFieldValue(el, String(nextValue));\n dispatchNativeFieldEvent(el, 'input');\n dispatchNativeFieldEvent(el, 'change');\n spawnSparkles(nextValue);\n }\n function handleKeydown(e: KeyboardEvent, star: number) {\n const next = ratingControl.nextFromKey(e.key, star);\n\n if (next == null) return;\n\n e.preventDefault();\n select(next, e);\n\n const buttons = getStarButtons();\n\n buttons[next - 1]?.focus();\n }\n\n const stars = computed(() => {\n const max = Number(props.max?.value) || 5;\n\n return Array.from({ length: max }, (_, i) => i + 1);\n });\n\n bind({ attr: { size: props.size } });\n\n return html`\n <div\n class=\"stars\"\n part=\"stars\"\n role=\"radiogroup\"\n aria-label=\"${props.label}\"\n aria-describedby=\"${ariaDescribedBy}\">\n ${() =>\n stars.value.map(\n (star) => html`\n <button\n class=\"star-btn\"\n part=\"star\"\n type=\"button\"\n role=\"radio\"\n aria-label=\"${() => `${star} ${star === 1 ? 'star' : 'stars'}`}\"\n aria-checked=\"${() => String(star === normalizedValue.value)}\"\n data-star=\"${star}\"\n ?data-filled=\"${() => star <= displayValue.value}\"\n disabled=\"${() => (!isInteractive.value ? true : null)}\"\n @click=\"${(e: Event) => select(star, e)}\"\n @pointerenter=\"${() => {\n if (isInteractive.value) hovered.value = star;\n }}\"\n @pointerleave=\"${() => {\n hovered.value = null;\n }}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, star)}\">\n <ore-icon name=\"star\" size=\"var(--_star-size)\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n `,\n )}\n <div class=\"sparkle-layer\"></div>\n </div>\n ${renderHelperRegion(assistiveId, errorText, helperText)}\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin({}), coarsePointerMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"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"}