@scalar/components 0.30.6 → 0.31.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 (41) hide show
  1. package/README.md +6 -0
  2. package/dist/components/ScalarColorModeToggle/ScalarColorModeToggleButton.vue.d.ts.map +1 -1
  3. package/dist/components/ScalarColorModeToggle/ScalarColorModeToggleButton.vue.js.map +1 -1
  4. package/dist/components/ScalarColorModeToggle/ScalarColorModeToggleButton.vue.script.js +1 -1
  5. package/dist/components/ScalarColorModeToggle/ScalarColorModeToggleButton.vue.script.js.map +1 -1
  6. package/dist/components/ScalarCombobox/ScalarComboboxOption.vue.js.map +1 -1
  7. package/dist/components/ScalarCombobox/ScalarComboboxOption.vue.script.js +1 -1
  8. package/dist/components/ScalarCombobox/ScalarComboboxOption.vue.script.js.map +1 -1
  9. package/dist/components/ScalarCombobox/ScalarComboboxOptions.vue.d.ts.map +1 -1
  10. package/dist/components/ScalarCombobox/ScalarComboboxOptions.vue.js.map +1 -1
  11. package/dist/components/ScalarCombobox/ScalarComboboxOptions.vue.script.js +3 -3
  12. package/dist/components/ScalarCombobox/ScalarComboboxOptions.vue.script.js.map +1 -1
  13. package/dist/components/ScalarCombobox/ScalarComboboxPopover.vue.d.ts.map +1 -1
  14. package/dist/components/ScalarCombobox/ScalarComboboxPopover.vue.js.map +1 -1
  15. package/dist/components/ScalarCombobox/ScalarComboboxPopover.vue.script.js +2 -3
  16. package/dist/components/ScalarCombobox/ScalarComboboxPopover.vue.script.js.map +1 -1
  17. package/dist/components/ScalarDropdown/ScalarDropdownMenu.vue.d.ts +0 -2
  18. package/dist/components/ScalarDropdown/ScalarDropdownMenu.vue.d.ts.map +1 -1
  19. package/dist/components/ScalarDropdown/ScalarDropdownMenu.vue.js.map +1 -1
  20. package/dist/components/ScalarDropdown/ScalarDropdownMenu.vue.script.js +4 -5
  21. package/dist/components/ScalarDropdown/ScalarDropdownMenu.vue.script.js.map +1 -1
  22. package/dist/components/ScalarFloating/ScalarFloatingBackdrop.vue.d.ts +6 -12
  23. package/dist/components/ScalarFloating/ScalarFloatingBackdrop.vue.d.ts.map +1 -1
  24. package/dist/components/ScalarFloating/ScalarFloatingBackdrop.vue.js.map +1 -1
  25. package/dist/components/ScalarFloating/ScalarFloatingBackdrop.vue.script.js +1 -1
  26. package/dist/components/ScalarFloating/ScalarFloatingBackdrop.vue.script.js.map +1 -1
  27. package/dist/components/ScalarListbox/ScalarListbox.vue.d.ts.map +1 -1
  28. package/dist/components/ScalarListbox/ScalarListbox.vue.js.map +1 -1
  29. package/dist/components/ScalarListbox/ScalarListbox.vue.script.js +3 -4
  30. package/dist/components/ScalarListbox/ScalarListbox.vue.script.js.map +1 -1
  31. package/dist/components/ScalarListbox/ScalarListboxItem.vue.js.map +1 -1
  32. package/dist/components/ScalarListbox/ScalarListboxItem.vue.script.js +1 -1
  33. package/dist/components/ScalarListbox/ScalarListboxItem.vue.script.js.map +1 -1
  34. package/dist/components/ScalarPopover/ScalarPopover.vue.d.ts.map +1 -1
  35. package/dist/components/ScalarPopover/ScalarPopover.vue.js.map +1 -1
  36. package/dist/components/ScalarPopover/ScalarPopover.vue.script.js +2 -3
  37. package/dist/components/ScalarPopover/ScalarPopover.vue.script.js.map +1 -1
  38. package/dist/components/ScalarPopover/types.d.ts +0 -5
  39. package/dist/components/ScalarPopover/types.d.ts.map +1 -1
  40. package/dist/style.css +17 -16
  41. package/package.json +4 -4
package/README.md CHANGED
@@ -114,6 +114,12 @@ Since you can directly target the reference element with Tailwind classes any cl
114
114
  </ScalarPopover>
115
115
  ```
116
116
 
117
+ The floating element also paints its own surface: `rounded-xl bg-b-1 dark:bg-b-1.5 shadow-md inset-shadow-border`. To change the background, override both modes, since `bg-*` alone does not replace the `dark:` variant:
118
+
119
+ ```html
120
+ <ScalarPopover class="bg-b-2 dark:bg-b-2">...</ScalarPopover>
121
+ ```
122
+
117
123
  ## CSS Layers
118
124
 
119
125
  The components package uses the same [CSS Layers](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) as the themes package to apply the theme styles. For more information see the [themes README](https://github.com/scalar/scalar/tree/main/packages/themes).
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarColorModeToggleButton.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarColorModeToggle/ScalarColorModeToggleButton.vue"],"names":[],"mappings":"AA6DA;;;;;;;;;;GAUG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;IASlB,yCAAyC;iBAC5B,OAAO;;;;IADpB,yCAAyC;iBAC5B,OAAO;;;kFAsFhB,CAAC"}
1
+ {"version":3,"file":"ScalarColorModeToggleButton.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarColorModeToggle/ScalarColorModeToggleButton.vue"],"names":[],"mappings":"AA6DA;;;;;;;;;;GAUG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;IASlB,yCAAyC;iBAC5B,OAAO;;;;IADpB,yCAAyC;iBAC5B,OAAO;;;kFAuFhB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarColorModeToggleButton.vue.js","names":[],"sources":["../../../src/components/ScalarColorModeToggle/ScalarColorModeToggleButton.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type ScalarColorModeToggle from './ScalarColorModeToggle.vue'\nimport ScalarColorModeToggleIcon from './ScalarColorModeToggleIcon.vue'\n\n/**\n * Scalar Color Mode Toggle Button component\n *\n * A dumb button that toggles between a sun and moon icon.\n *\n * If you need a toggle that is aware of and sets color mode,\n * you want {@link ScalarColorModeToggle} instead.\n *\n * @example\n * <ScalarColorModeToggleButton v-model=\"isDarkMode\" />\n */\nexport default {}\n</script>\n<script lang=\"ts\" setup>\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n\n/** Whether the toggle is in dark mode */\nconst model = defineModel<boolean>()\n</script>\n<template>\n <button\n :aria-pressed=\"model\"\n type=\"button\"\n v-bind=\"\n cx(\n 'group/toggle flex h-6 w-[38px] brightness-lifted -mx-px items-center py-1.5 -my-1.5 relative outline-none',\n )\n \"\n @click=\"model = !model\">\n <!-- Background -->\n <div\n class=\"h-3 w-full bg-border mx-px rounded-xl group-focus-visible/toggle:outline -outline-offset-1\" />\n <!-- Slider -->\n <div\n class=\"size-[23px] left-border absolute border rounded-full flex items-center justify-center bg-b-1 group-focus-visible/toggle:outline -outline-offset-1 transition-transform duration-300 ease-in-out\"\n :class=\"{ 'translate-x-[14px]': model }\">\n <!-- Icon -->\n <ScalarColorModeToggleIcon\n is=\"div\"\n :mode=\"model ? 'dark' : 'light'\" />\n </div>\n </button>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ScalarColorModeToggleButton.vue.js","names":[],"sources":["../../../src/components/ScalarColorModeToggle/ScalarColorModeToggleButton.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type ScalarColorModeToggle from './ScalarColorModeToggle.vue'\nimport ScalarColorModeToggleIcon from './ScalarColorModeToggleIcon.vue'\n\n/**\n * Scalar Color Mode Toggle Button component\n *\n * A dumb button that toggles between a sun and moon icon.\n *\n * If you need a toggle that is aware of and sets color mode,\n * you want {@link ScalarColorModeToggle} instead.\n *\n * @example\n * <ScalarColorModeToggleButton v-model=\"isDarkMode\" />\n */\nexport default {}\n</script>\n<script lang=\"ts\" setup>\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n\n/** Whether the toggle is in dark mode */\nconst model = defineModel<boolean>()\n</script>\n<template>\n <button\n :aria-pressed=\"model\"\n type=\"button\"\n v-bind=\"\n cx(\n 'group/toggle flex h-6 w-[38px] -mx-px items-center py-1.5 -my-1.5 relative outline-none',\n )\n \"\n @click=\"model = !model\">\n <!-- Background -->\n <div\n class=\"h-3 w-full bg-border mx-px rounded-xl group-focus-visible/toggle:outline -outline-offset-1\" />\n <!-- Slider -->\n <div\n class=\"size-[23px] left-border absolute border rounded-full flex items-center justify-center bg-b-1 dark:bg-b-1.5 group-focus-visible/toggle:outline -outline-offset-1 transition-transform duration-300 ease-in-out\"\n :class=\"{ 'translate-x-[14px]': model }\">\n <!-- Icon -->\n <ScalarColorModeToggleIcon\n is=\"div\"\n :mode=\"model ? 'dark' : 'light'\" />\n </div>\n </button>\n</template>\n"],"mappings":""}
@@ -19,7 +19,7 @@ var ScalarColorModeToggleButton_vue_vue_type_script_setup_true_lang_default = /*
19
19
  return openBlock(), createElementBlock("button", mergeProps({
20
20
  "aria-pressed": model.value,
21
21
  type: "button"
22
- }, unref(cx)("group/toggle flex h-6 w-[38px] brightness-lifted -mx-px items-center py-1.5 -my-1.5 relative outline-none"), { onClick: _cache[0] || (_cache[0] = ($event) => model.value = !model.value) }), [_cache[1] || (_cache[1] = createElementVNode("div", { class: "h-3 w-full bg-border mx-px rounded-xl group-focus-visible/toggle:outline -outline-offset-1" }, null, -1)), createElementVNode("div", { class: normalizeClass(["size-[23px] left-border absolute border rounded-full flex items-center justify-center bg-b-1 group-focus-visible/toggle:outline -outline-offset-1 transition-transform duration-300 ease-in-out", { "translate-x-[14px]": model.value }]) }, [createVNode(ScalarColorModeToggleIcon_default, {
22
+ }, unref(cx)("group/toggle flex h-6 w-[38px] -mx-px items-center py-1.5 -my-1.5 relative outline-none"), { onClick: _cache[0] || (_cache[0] = ($event) => model.value = !model.value) }), [_cache[1] || (_cache[1] = createElementVNode("div", { class: "h-3 w-full bg-border mx-px rounded-xl group-focus-visible/toggle:outline -outline-offset-1" }, null, -1)), createElementVNode("div", { class: normalizeClass(["size-[23px] left-border absolute border rounded-full flex items-center justify-center bg-b-1 dark:bg-b-1.5 group-focus-visible/toggle:outline -outline-offset-1 transition-transform duration-300 ease-in-out", { "translate-x-[14px]": model.value }]) }, [createVNode(ScalarColorModeToggleIcon_default, {
23
23
  is: "div",
24
24
  mode: model.value ? "dark" : "light"
25
25
  }, null, 8, ["mode"])], 2)], 16, _hoisted_1);
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarColorModeToggleButton.vue.script.js","names":[],"sources":["../../../src/components/ScalarColorModeToggle/ScalarColorModeToggleButton.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type ScalarColorModeToggle from './ScalarColorModeToggle.vue'\nimport ScalarColorModeToggleIcon from './ScalarColorModeToggleIcon.vue'\n\n/**\n * Scalar Color Mode Toggle Button component\n *\n * A dumb button that toggles between a sun and moon icon.\n *\n * If you need a toggle that is aware of and sets color mode,\n * you want {@link ScalarColorModeToggle} instead.\n *\n * @example\n * <ScalarColorModeToggleButton v-model=\"isDarkMode\" />\n */\nexport default {}\n</script>\n<script lang=\"ts\" setup>\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n\n/** Whether the toggle is in dark mode */\nconst model = defineModel<boolean>()\n</script>\n<template>\n <button\n :aria-pressed=\"model\"\n type=\"button\"\n v-bind=\"\n cx(\n 'group/toggle flex h-6 w-[38px] brightness-lifted -mx-px items-center py-1.5 -my-1.5 relative outline-none',\n )\n \"\n @click=\"model = !model\">\n <!-- Background -->\n <div\n class=\"h-3 w-full bg-border mx-px rounded-xl group-focus-visible/toggle:outline -outline-offset-1\" />\n <!-- Slider -->\n <div\n class=\"size-[23px] left-border absolute border rounded-full flex items-center justify-center bg-b-1 group-focus-visible/toggle:outline -outline-offset-1 transition-transform duration-300 ease-in-out\"\n :class=\"{ 'translate-x-[14px]': model }\">\n <!-- Icon -->\n <ScalarColorModeToggleIcon\n is=\"div\"\n :mode=\"model ? 'dark' : 'light'\" />\n </div>\n </button>\n</template>\n"],"mappings":";;;;;;;;;;;;;;EAsBA,MAAM,EAAE,OAAO,UAAU;;EAGzB,MAAM,QAAQ,SAAoB,SAAA,YAAC;;uBAGjC,mBAqBS,UArBT,WAqBS;IApBN,gBAAc,MAAA;IACf,MAAK;MACU,MAAA,EAAA,CAAE,CAAA,2GAAA,GAAA,EAKhB,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,QAAK,CAAI,MAAA,OAAA,CAAA,GAAA,CAAA,OAAA,OAAA,OAAA,KAEjB,mBACuG,OAAA,EAArG,OAAM,6FAA4F,GAAA,MAAA,EAAA,IAEpG,mBAOM,OAAA,EANJ,OAAK,eAAA,CAAC,mMAAiM,EAAA,sBACvK,MAAA,MAAK,CAAA,CAAA,EAAA,GAAA,CAErC,YAEqC,mCAAA;IADnC,IAAG;IACF,MAAM,MAAA,QAAK,SAAA"}
1
+ {"version":3,"file":"ScalarColorModeToggleButton.vue.script.js","names":[],"sources":["../../../src/components/ScalarColorModeToggle/ScalarColorModeToggleButton.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type ScalarColorModeToggle from './ScalarColorModeToggle.vue'\nimport ScalarColorModeToggleIcon from './ScalarColorModeToggleIcon.vue'\n\n/**\n * Scalar Color Mode Toggle Button component\n *\n * A dumb button that toggles between a sun and moon icon.\n *\n * If you need a toggle that is aware of and sets color mode,\n * you want {@link ScalarColorModeToggle} instead.\n *\n * @example\n * <ScalarColorModeToggleButton v-model=\"isDarkMode\" />\n */\nexport default {}\n</script>\n<script lang=\"ts\" setup>\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n\n/** Whether the toggle is in dark mode */\nconst model = defineModel<boolean>()\n</script>\n<template>\n <button\n :aria-pressed=\"model\"\n type=\"button\"\n v-bind=\"\n cx(\n 'group/toggle flex h-6 w-[38px] -mx-px items-center py-1.5 -my-1.5 relative outline-none',\n )\n \"\n @click=\"model = !model\">\n <!-- Background -->\n <div\n class=\"h-3 w-full bg-border mx-px rounded-xl group-focus-visible/toggle:outline -outline-offset-1\" />\n <!-- Slider -->\n <div\n class=\"size-[23px] left-border absolute border rounded-full flex items-center justify-center bg-b-1 dark:bg-b-1.5 group-focus-visible/toggle:outline -outline-offset-1 transition-transform duration-300 ease-in-out\"\n :class=\"{ 'translate-x-[14px]': model }\">\n <!-- Icon -->\n <ScalarColorModeToggleIcon\n is=\"div\"\n :mode=\"model ? 'dark' : 'light'\" />\n </div>\n </button>\n</template>\n"],"mappings":";;;;;;;;;;;;;;EAsBA,MAAM,EAAE,OAAO,UAAU;;EAGzB,MAAM,QAAQ,SAAoB,SAAA,YAAC;;uBAGjC,mBAqBS,UArBT,WAqBS;IApBN,gBAAc,MAAA;IACf,MAAK;MACU,MAAA,EAAA,CAAE,CAAA,yFAAA,GAAA,EAKhB,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,QAAK,CAAI,MAAA,OAAA,CAAA,GAAA,CAAA,OAAA,OAAA,OAAA,KAEjB,mBACuG,OAAA,EAArG,OAAM,6FAA4F,GAAA,MAAA,EAAA,IAEpG,mBAOM,OAAA,EANJ,OAAK,eAAA,CAAC,iNAA+M,EAAA,sBACrL,MAAA,MAAK,CAAA,CAAA,EAAA,GAAA,CAErC,YAEqC,mCAAA;IADnC,IAAG;IACF,MAAM,MAAA,QAAK,SAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarComboboxOption.vue.js","names":[],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxOption.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Option component\n *\n * A single selectable option within a combobox list.\n * Handles active and selected states.\n *\n * @example\n * <ScalarComboboxOption :active=\"true\" :selected=\"false\">\n * Option Label\n * </ScalarComboboxOption>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { cva, cx } from '@scalar/use-hooks/useBindCx'\n\nconst { active, selected } = defineProps<{\n active?: boolean\n selected?: boolean\n}>()\n\nconst variants = cva({\n base: [\n // Group\n 'group/item',\n // Layout\n 'flex min-w-0 items-center gap-1.5 rounded px-2 py-1.5 text-left',\n // Text / background style\n 'truncate bg-transparent text-c-1',\n // Interaction\n 'cursor-pointer hover:bg-b-2',\n ],\n variants: {\n selected: { true: 'text-c-1' },\n active: { true: 'bg-b-2' },\n },\n})\n</script>\n<template>\n <li\n :aria-selected=\"selected\"\n :class=\"cx(variants({ active, selected }))\"\n role=\"option\"\n tabindex=\"-1\">\n <slot\n :active\n :selected />\n </li>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ScalarComboboxOption.vue.js","names":[],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxOption.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Option component\n *\n * A single selectable option within a combobox list.\n * Handles active and selected states.\n *\n * @example\n * <ScalarComboboxOption :active=\"true\" :selected=\"false\">\n * Option Label\n * </ScalarComboboxOption>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { cva, cx } from '@scalar/use-hooks/useBindCx'\n\nconst { active, selected } = defineProps<{\n active?: boolean\n selected?: boolean\n}>()\n\nconst variants = cva({\n base: [\n // Group\n 'group/item',\n // Layout\n 'flex min-w-0 items-center gap-1.5 rounded-md px-2 py-1.5 text-left',\n // Text / background style\n 'truncate bg-transparent text-c-1',\n // Interaction\n 'cursor-pointer hover:bg-b-2',\n ],\n variants: {\n selected: { true: 'text-c-1' },\n active: { true: 'bg-b-2' },\n },\n})\n</script>\n<template>\n <li\n :aria-selected=\"selected\"\n :class=\"cx(variants({ active, selected }))\"\n role=\"option\"\n tabindex=\"-1\">\n <slot\n :active\n :selected />\n </li>\n</template>\n"],"mappings":""}
@@ -12,7 +12,7 @@ var ScalarComboboxOption_vue_vue_type_script_setup_true_lang_default = /*@__PURE
12
12
  const variants = cva({
13
13
  base: [
14
14
  "group/item",
15
- "flex min-w-0 items-center gap-1.5 rounded px-2 py-1.5 text-left",
15
+ "flex min-w-0 items-center gap-1.5 rounded-md px-2 py-1.5 text-left",
16
16
  "truncate bg-transparent text-c-1",
17
17
  "cursor-pointer hover:bg-b-2"
18
18
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarComboboxOption.vue.script.js","names":[],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxOption.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Option component\n *\n * A single selectable option within a combobox list.\n * Handles active and selected states.\n *\n * @example\n * <ScalarComboboxOption :active=\"true\" :selected=\"false\">\n * Option Label\n * </ScalarComboboxOption>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { cva, cx } from '@scalar/use-hooks/useBindCx'\n\nconst { active, selected } = defineProps<{\n active?: boolean\n selected?: boolean\n}>()\n\nconst variants = cva({\n base: [\n // Group\n 'group/item',\n // Layout\n 'flex min-w-0 items-center gap-1.5 rounded px-2 py-1.5 text-left',\n // Text / background style\n 'truncate bg-transparent text-c-1',\n // Interaction\n 'cursor-pointer hover:bg-b-2',\n ],\n variants: {\n selected: { true: 'text-c-1' },\n active: { true: 'bg-b-2' },\n },\n})\n</script>\n<template>\n <li\n :aria-selected=\"selected\"\n :class=\"cx(variants({ active, selected }))\"\n role=\"option\"\n tabindex=\"-1\">\n <slot\n :active\n :selected />\n </li>\n</template>\n"],"mappings":";;;;;;;;;;;EAuBA,MAAM,WAAW,IAAI;GACnB,MAAM;IAEJ;IAEA;IAEA;IAEA;GACF;GACA,UAAU;IACR,UAAU,EAAE,MAAM,WAAW;IAC7B,QAAQ,EAAE,MAAM,SAAS;GAC3B;EACF,CAAC;;uBAGC,mBAQK,MAAA;IAPF,iBAAe,QAAA;IACf,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,MAAA,QAAA,CAAQ,CAAA;KAAA,QAAG,QAAA;KAAM,UAAE,QAAA;IAAQ,CAAA,CAAA,CAAA;IACtC,MAAK;IACL,UAAS;OACT,WAEc,KAAA,QAAA,WAAA;IADX,QAAA,QAAA;IACA,UAAA,QAAA"}
1
+ {"version":3,"file":"ScalarComboboxOption.vue.script.js","names":[],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxOption.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Option component\n *\n * A single selectable option within a combobox list.\n * Handles active and selected states.\n *\n * @example\n * <ScalarComboboxOption :active=\"true\" :selected=\"false\">\n * Option Label\n * </ScalarComboboxOption>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { cva, cx } from '@scalar/use-hooks/useBindCx'\n\nconst { active, selected } = defineProps<{\n active?: boolean\n selected?: boolean\n}>()\n\nconst variants = cva({\n base: [\n // Group\n 'group/item',\n // Layout\n 'flex min-w-0 items-center gap-1.5 rounded-md px-2 py-1.5 text-left',\n // Text / background style\n 'truncate bg-transparent text-c-1',\n // Interaction\n 'cursor-pointer hover:bg-b-2',\n ],\n variants: {\n selected: { true: 'text-c-1' },\n active: { true: 'bg-b-2' },\n },\n})\n</script>\n<template>\n <li\n :aria-selected=\"selected\"\n :class=\"cx(variants({ active, selected }))\"\n role=\"option\"\n tabindex=\"-1\">\n <slot\n :active\n :selected />\n </li>\n</template>\n"],"mappings":";;;;;;;;;;;EAuBA,MAAM,WAAW,IAAI;GACnB,MAAM;IAEJ;IAEA;IAEA;IAEA;GACF;GACA,UAAU;IACR,UAAU,EAAE,MAAM,WAAW;IAC7B,QAAQ,EAAE,MAAM,SAAS;GAC3B;EACF,CAAC;;uBAGC,mBAQK,MAAA;IAPF,iBAAe,QAAA;IACf,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,MAAA,QAAA,CAAQ,CAAA;KAAA,QAAG,QAAA;KAAM,UAAE,QAAA;IAAQ,CAAA,CAAA,CAAA;IACtC,MAAK;IACL,UAAS;OACT,WAEc,KAAA,QAAA,WAAA;IADX,QAAA,QAAA;IACA,UAAA,QAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarComboboxOptions.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarCombobox/ScalarComboboxOptions.vue"],"names":[],"mappings":"AAwVA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,MAAM,EACX,KAAK,WAAW,EAChB,KAAK,eAAe,EAErB,MAAM,SAAS,CAAA;AAGhB;;;;;;;;GAQG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY,GAAK,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,SAAS,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,EAC1F,aAAa,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAC9D,YAAY,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,EAC3G,gBAAgB,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAClE;WAwhBO,OAAO,KAAK,EAAE,WAAW,GAAG,mBAAmB,CAAC;QAthBtD,6CAA6C;iBACpC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9B,sDAAsD;sBACxC,MAAM;QACpB,+CAA+C;qBAClC,MAAM;QACnB,+DAA+D;oBACnD,MAAM;QAClB,+DAA+D;gBACvD,MAAM,IAAI;QAClB;;;;;WAKG;mBACQ,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,qEAAqE;sBACvD,OAAO;;qBA6LV,CAAC,EAAE;;;;KAuU2E,CAAC,GAAG,CAAC,OAAO,UAAU,SAAS;QAAE,oBAAoB,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAC5J,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI;WACtB,GAAG;;UAEJ,2EAAoC;EAEvC,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;CAAI,CAAC;AACzF,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,CAAC,GAAG,EAAE,CAAC"}
1
+ {"version":3,"file":"ScalarComboboxOptions.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarCombobox/ScalarComboboxOptions.vue"],"names":[],"mappings":"AAyVA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,MAAM,EACX,KAAK,WAAW,EAChB,KAAK,eAAe,EAErB,MAAM,SAAS,CAAA;AAGhB;;;;;;;;GAQG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY,GAAK,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,SAAS,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,EAC1F,aAAa,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAC9D,YAAY,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,EAC3G,gBAAgB,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAClE;WAyhBO,OAAO,KAAK,EAAE,WAAW,GAAG,mBAAmB,CAAC;QAvhBtD,6CAA6C;iBACpC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9B,sDAAsD;sBACxC,MAAM;QACpB,+CAA+C;qBAClC,MAAM;QACnB,+DAA+D;oBACnD,MAAM;QAClB,+DAA+D;gBACvD,MAAM,IAAI;QAClB;;;;;WAKG;mBACQ,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,qEAAqE;sBACvD,OAAO;;qBA6LV,CAAC,EAAE;;;;KAwU2E,CAAC,GAAG,CAAC,OAAO,UAAU,SAAS;QAAE,oBAAoB,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAC5J,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI;WACtB,GAAG;;UAEJ,2EAAoC;EAEvC,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;CAAI,CAAC;AACzF,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,CAAC,GAAG,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarComboboxOptions.vue.js","names":[],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxOptions.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Options component\n *\n * Renders the searchable option list for a combobox, including\n * filtering, keyboard navigation, and an optional \"add new\" action.\n *\n * @example\n * <ScalarComboboxOptions v-model=\"selected\" :options=\"options\" />\n */\nexport default {}\n</script>\n\n<!-- prettier-ignore-attribute generic -->\n<script\n setup\n lang=\"ts\"\n generic=\"O extends Option = Option, G extends OptionGroup<O> = OptionGroup<O>\">\nimport { filterByOptionLabel } from '@/components/ScalarCombobox/filter-by-option-label'\nimport { ScalarIconMagnifyingGlass, ScalarIconPlus } from '@scalar/icons'\nimport { computed, onMounted, ref, useId, watch } from 'vue'\n\nimport { ScalarListboxCheckbox } from '../ScalarListbox'\nimport ComboboxOption from './ScalarComboboxOption.vue'\nimport ComboboxOptionGroup from './ScalarComboboxOptionGroup.vue'\nimport {\n type ComboboxEmits,\n type ComboboxSlots,\n type FilterFunction,\n type Option,\n type OptionGroup,\n type OptionsOrGroups,\n isGroups,\n} from './types'\n\nconst {\n options: optionsOrGroups,\n placeholder,\n inputLabel,\n noResults,\n close,\n filterFn = filterByOptionLabel,\n multiselect,\n} = defineProps<{\n /** The options to display in the combobox */\n options: OptionsOrGroups<O, G>\n /** The placeholder text to display in the combobox */\n placeholder?: string\n /** An accessible label for the search input */\n inputLabel?: string\n /** The message to display when filtering returns no options */\n noResults?: string\n /** Close the popover without changing the current selection */\n close?: () => void\n /**\n * A function to filter the options based on a query,\n * if not provided, the options will be filtered by option label\n *\n * @see {@link FilterFunction} for more information\n */\n filterFn?: FilterFunction<O, G>\n /** Whether the combobox is in multiselect mode, defaults to false */\n multiselect?: boolean\n}>()\n\nconst emit = defineEmits<ComboboxEmits>()\n\nconst model = defineModel<O[]>({ default: () => [] })\n\nconst slots = defineSlots<Omit<ComboboxSlots<O, G>, 'default'>>()\n\ndefineOptions({ inheritAttrs: false })\n\n/** A unique ID for the combobox */\nconst id = `scalar-combobox-items-${useId()}`\n\n/** A static option entry for the \"Add a new option\" option */\nconst addOption: Option = { id: `${useId()}-add`, label: 'Add a new option' }\n\n/** Generate a unique ID for an option */\nfunction getOptionId(option: Option) {\n return `${id}-${option.id}`\n}\n\n/** A flat list of all options */\nconst options = computed<O[]>(() =>\n isGroups(optionsOrGroups)\n ? optionsOrGroups.flatMap((group) => group.options)\n : optionsOrGroups,\n)\n\n/** An list of all groups */\nconst groups = computed<G[]>(\n () =>\n isGroups(optionsOrGroups)\n ? optionsOrGroups // G extends OptionGroup<O>\n : /*\n We know G is an unextended OptionGroup<O> here because of the\n structure of the component props so we can cast it to G\n */\n [{ label: '', options: optionsOrGroups } as G], // G is OptionGroup<O>\n)\n\nconst query = ref<string>('')\nconst activeRef = ref<Option | undefined>(model.value?.[0] ?? options.value[0])\n\n// Clear the query on open and close\nonMounted(() => {\n // Clear the query\n query.value = ''\n\n // Set the active option to the selected option or the first option\n activeRef.value = model.value?.[0] ?? options.value[0]\n\n // Scroll to the selected option\n const selected = model.value[0]\n if (selected) {\n setTimeout(() => {\n const value = model.value[0]\n if (!value) {\n return\n }\n\n document\n ?.getElementById(getOptionId(value))\n ?.scrollIntoView({ block: 'nearest' })\n }, 10)\n }\n})\n\n// Set the top option as active when searching\nwatch(\n () => query.value,\n () => (activeRef.value = withAdd.value[0]),\n)\n\n/** The filtered list of options */\nconst filtered = computed<O[]>(() =>\n filterFn(query.value, options.value, groups.value),\n)\n\n/** The list of filtered options with the \"Add a new option\" option */\nconst withAdd = computed<Option[]>(() =>\n slots.add ? [...filtered.value, addOption] : filtered.value,\n)\n\nfunction toggleSelected(option: Option | undefined) {\n if (!option) {\n return\n }\n\n if (option.id === addOption.id) {\n addNew()\n return\n }\n\n if (multiselect) {\n // Remove from selection list\n if (model.value.some((o) => o.id === option.id)) {\n model.value = model.value.filter((o) => o.id !== option.id)\n }\n // Add to selection list\n else {\n model.value = [\n ...model.value,\n options.value.find((o) => o.id === option.id)!,\n ]\n }\n } else {\n // Set selection for single select mode\n model.value = [options.value.find((o) => o.id === option.id)!]\n }\n}\n\nfunction moveActive(dir: 1 | -1) {\n const list = withAdd.value\n\n // Find active index\n const activeIdx = list.findIndex(\n (option) => option.id === activeRef.value?.id,\n )\n\n // Calculate next index and exit if it's out of bounds\n const nextIdx = activeIdx + dir\n\n if (nextIdx < 0 || nextIdx > list.length - 1) {\n return\n }\n\n activeRef.value = list[nextIdx]! // We know it's in bounds from the check above\n\n if (!activeRef.value) {\n return\n }\n\n // Scroll to the active option\n document?.getElementById(getOptionId(activeRef.value))?.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n })\n}\n\nfunction addNew() {\n emit('add')\n query.value = ''\n}\n\n/**\n * Space toggles the active option in multiselect mode while the search box is empty.\n *\n * The options look like checkboxes, so keyboard users press Space to toggle them. Without this\n * handler Space types a leading space into the query, which filters out every option whose label\n * has no space and hides the whole list without any feedback (found by an accessibility audit).\n * Once a query has been typed, Space keeps inserting a character so multi-word labels stay\n * searchable. Key auto-repeat is ignored so holding Space after opening the popover with it does\n * not toggle the option repeatedly, and IME composition is left alone.\n */\nconst handleSpace = (event: KeyboardEvent): void => {\n if (!multiselect || query.value !== '' || event.isComposing) {\n return\n }\n // Suppress repeated spaces too, so holding the key does not start filtering.\n event.preventDefault()\n if (!event.repeat) {\n toggleSelected(activeRef.value)\n }\n}\n\n// Manual autofocus for the input\nconst input = ref<HTMLInputElement | null>(null)\n\n// This must be a setTimeout to ensure there is no scroll jump. nextTick does not work here.\nonMounted(() => setTimeout(() => input.value?.focus(), 0))\n</script>\n<template>\n <div class=\"relative flex\">\n <ScalarIconMagnifyingGlass\n class=\"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-c-3 size-4\" />\n <input\n ref=\"input\"\n v-model=\"query\"\n :aria-activedescendant=\"activeRef ? getOptionId(activeRef) : undefined\"\n aria-autocomplete=\"list\"\n :aria-controls=\"id\"\n :aria-expanded=\"Boolean(filtered.length || slots.add || noResults)\"\n :aria-label=\"inputLabel\"\n class=\"min-w-0 flex-1 rounded border-0 py-2.5 pl-8 pr-3 leading-none text-c-1 -outline-offset-1\"\n data-1p-ignore\n :placeholder\n role=\"combobox\"\n tabindex=\"0\"\n type=\"text\"\n @keydown.down.prevent=\"moveActive(1)\"\n @keydown.enter.prevent=\"activeRef && toggleSelected(activeRef)\"\n @keydown.esc.prevent=\"close?.()\"\n @keydown.space=\"handleSpace\"\n @keydown.up.prevent=\"moveActive(-1)\" />\n </div>\n <ul\n v-show=\"filtered.length || slots.add || noResults\"\n :id=\"id\"\n :aria-multiselectable=\"multiselect\"\n class=\"border-t p-0.75 custom-scroll overscroll-contain flex-1 min-h-0\"\n role=\"listbox\"\n tabindex=\"-1\">\n <li\n v-if=\"!filtered.length && !slots.add && noResults\"\n class=\"text-c-3 px-2.5 py-2\"\n role=\"status\">\n {{ noResults }}\n </li>\n <ComboboxOptionGroup\n v-for=\"(group, i) in groups\"\n :id=\"`${id}-group-${i}`\"\n :key=\"i\"\n :hidden=\"\n // Only show the group label if there are some results\n !group.options.some((o) => filtered.some((f) => f.id === o.id)) ||\n // And it has a label\n !group.label\n \">\n <template #label>\n <slot\n v-if=\"$slots.group\"\n :group\n name=\"group\" />\n <template v-else>\n {{ group.label }}\n </template>\n </template>\n <template\n v-for=\"option in filtered\"\n :key=\"option.id\">\n <ComboboxOption\n v-if=\"group.options.some((o) => o.id === option.id)\"\n :id=\"getOptionId(option)\"\n v-slot=\"{ active, selected }\"\n :active=\"activeRef?.id === option.id\"\n :selected=\"model.some((o) => o.id === option.id)\"\n @click=\"toggleSelected(option)\"\n @mousedown.prevent\n @mouseenter=\"activeRef = option\">\n <slot\n v-if=\"$slots.option\"\n :active\n name=\"option\"\n :option\n :selected />\n <template v-else>\n <ScalarListboxCheckbox\n :multiselect\n :selected=\"model.some((o) => o.id === option.id)\" />\n <span class=\"inline-block min-w-0 flex-1 truncate text-c-1\">\n {{ option.label }}\n </span>\n </template>\n </ComboboxOption>\n </template>\n </ComboboxOptionGroup>\n <ComboboxOption\n v-if=\"slots.add\"\n :id=\"getOptionId(addOption)\"\n v-slot=\"{ active }\"\n :active=\"activeRef?.id === addOption.id\"\n @click=\"addNew\"\n @mousedown.prevent\n @mouseenter=\"activeRef = addOption\">\n <ScalarIconPlus class=\"size-4 p-px\" />\n <slot\n :active\n name=\"add\" />\n </ComboboxOption>\n </ul>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ScalarComboboxOptions.vue.js","names":[],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxOptions.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Options component\n *\n * Renders the searchable option list for a combobox, including\n * filtering, keyboard navigation, and an optional \"add new\" action.\n *\n * @example\n * <ScalarComboboxOptions v-model=\"selected\" :options=\"options\" />\n */\nexport default {}\n</script>\n\n<!-- prettier-ignore-attribute generic -->\n<script\n setup\n lang=\"ts\"\n generic=\"O extends Option = Option, G extends OptionGroup<O> = OptionGroup<O>\">\nimport { filterByOptionLabel } from '@/components/ScalarCombobox/filter-by-option-label'\nimport { ScalarIconMagnifyingGlass, ScalarIconPlus } from '@scalar/icons'\nimport { computed, onMounted, ref, useId, watch } from 'vue'\n\nimport { ScalarListboxCheckbox } from '../ScalarListbox'\nimport ComboboxOption from './ScalarComboboxOption.vue'\nimport ComboboxOptionGroup from './ScalarComboboxOptionGroup.vue'\nimport {\n type ComboboxEmits,\n type ComboboxSlots,\n type FilterFunction,\n type Option,\n type OptionGroup,\n type OptionsOrGroups,\n isGroups,\n} from './types'\n\nconst {\n options: optionsOrGroups,\n placeholder,\n inputLabel,\n noResults,\n close,\n filterFn = filterByOptionLabel,\n multiselect,\n} = defineProps<{\n /** The options to display in the combobox */\n options: OptionsOrGroups<O, G>\n /** The placeholder text to display in the combobox */\n placeholder?: string\n /** An accessible label for the search input */\n inputLabel?: string\n /** The message to display when filtering returns no options */\n noResults?: string\n /** Close the popover without changing the current selection */\n close?: () => void\n /**\n * A function to filter the options based on a query,\n * if not provided, the options will be filtered by option label\n *\n * @see {@link FilterFunction} for more information\n */\n filterFn?: FilterFunction<O, G>\n /** Whether the combobox is in multiselect mode, defaults to false */\n multiselect?: boolean\n}>()\n\nconst emit = defineEmits<ComboboxEmits>()\n\nconst model = defineModel<O[]>({ default: () => [] })\n\nconst slots = defineSlots<Omit<ComboboxSlots<O, G>, 'default'>>()\n\ndefineOptions({ inheritAttrs: false })\n\n/** A unique ID for the combobox */\nconst id = `scalar-combobox-items-${useId()}`\n\n/** A static option entry for the \"Add a new option\" option */\nconst addOption: Option = { id: `${useId()}-add`, label: 'Add a new option' }\n\n/** Generate a unique ID for an option */\nfunction getOptionId(option: Option) {\n return `${id}-${option.id}`\n}\n\n/** A flat list of all options */\nconst options = computed<O[]>(() =>\n isGroups(optionsOrGroups)\n ? optionsOrGroups.flatMap((group) => group.options)\n : optionsOrGroups,\n)\n\n/** An list of all groups */\nconst groups = computed<G[]>(\n () =>\n isGroups(optionsOrGroups)\n ? optionsOrGroups // G extends OptionGroup<O>\n : /*\n We know G is an unextended OptionGroup<O> here because of the\n structure of the component props so we can cast it to G\n */\n [{ label: '', options: optionsOrGroups } as G], // G is OptionGroup<O>\n)\n\nconst query = ref<string>('')\nconst activeRef = ref<Option | undefined>(model.value?.[0] ?? options.value[0])\n\n// Clear the query on open and close\nonMounted(() => {\n // Clear the query\n query.value = ''\n\n // Set the active option to the selected option or the first option\n activeRef.value = model.value?.[0] ?? options.value[0]\n\n // Scroll to the selected option\n const selected = model.value[0]\n if (selected) {\n setTimeout(() => {\n const value = model.value[0]\n if (!value) {\n return\n }\n\n document\n ?.getElementById(getOptionId(value))\n ?.scrollIntoView({ block: 'nearest' })\n }, 10)\n }\n})\n\n// Set the top option as active when searching\nwatch(\n () => query.value,\n () => (activeRef.value = withAdd.value[0]),\n)\n\n/** The filtered list of options */\nconst filtered = computed<O[]>(() =>\n filterFn(query.value, options.value, groups.value),\n)\n\n/** The list of filtered options with the \"Add a new option\" option */\nconst withAdd = computed<Option[]>(() =>\n slots.add ? [...filtered.value, addOption] : filtered.value,\n)\n\nfunction toggleSelected(option: Option | undefined) {\n if (!option) {\n return\n }\n\n if (option.id === addOption.id) {\n addNew()\n return\n }\n\n if (multiselect) {\n // Remove from selection list\n if (model.value.some((o) => o.id === option.id)) {\n model.value = model.value.filter((o) => o.id !== option.id)\n }\n // Add to selection list\n else {\n model.value = [\n ...model.value,\n options.value.find((o) => o.id === option.id)!,\n ]\n }\n } else {\n // Set selection for single select mode\n model.value = [options.value.find((o) => o.id === option.id)!]\n }\n}\n\nfunction moveActive(dir: 1 | -1) {\n const list = withAdd.value\n\n // Find active index\n const activeIdx = list.findIndex(\n (option) => option.id === activeRef.value?.id,\n )\n\n // Calculate next index and exit if it's out of bounds\n const nextIdx = activeIdx + dir\n\n if (nextIdx < 0 || nextIdx > list.length - 1) {\n return\n }\n\n activeRef.value = list[nextIdx]! // We know it's in bounds from the check above\n\n if (!activeRef.value) {\n return\n }\n\n // Scroll to the active option\n document?.getElementById(getOptionId(activeRef.value))?.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n })\n}\n\nfunction addNew() {\n emit('add')\n query.value = ''\n}\n\n/**\n * Space toggles the active option in multiselect mode while the search box is empty.\n *\n * The options look like checkboxes, so keyboard users press Space to toggle them. Without this\n * handler Space types a leading space into the query, which filters out every option whose label\n * has no space and hides the whole list without any feedback (found by an accessibility audit).\n * Once a query has been typed, Space keeps inserting a character so multi-word labels stay\n * searchable. Key auto-repeat is ignored so holding Space after opening the popover with it does\n * not toggle the option repeatedly, and IME composition is left alone.\n */\nconst handleSpace = (event: KeyboardEvent): void => {\n if (!multiselect || query.value !== '' || event.isComposing) {\n return\n }\n // Suppress repeated spaces too, so holding the key does not start filtering.\n event.preventDefault()\n if (!event.repeat) {\n toggleSelected(activeRef.value)\n }\n}\n\n// Manual autofocus for the input\nconst input = ref<HTMLInputElement | null>(null)\n\n// This must be a setTimeout to ensure there is no scroll jump. nextTick does not work here.\nonMounted(() => setTimeout(() => input.value?.focus(), 0))\n</script>\n<template>\n <!-- Inset to line up with the options below -->\n <div class=\"relative flex m-1 mb-0.75\">\n <ScalarIconMagnifyingGlass\n class=\"pointer-events-none absolute left-1.75 top-1/2 -translate-y-1/2 text-c-3 size-4\" />\n <input\n ref=\"input\"\n v-model=\"query\"\n :aria-activedescendant=\"activeRef ? getOptionId(activeRef) : undefined\"\n aria-autocomplete=\"list\"\n :aria-controls=\"id\"\n :aria-expanded=\"Boolean(filtered.length || slots.add || noResults)\"\n :aria-label=\"inputLabel\"\n class=\"min-w-0 flex-1 rounded-md border-0 py-1.5 pl-7.25 pr-1.75 leading-none text-c-1\"\n data-1p-ignore\n :placeholder\n role=\"combobox\"\n tabindex=\"0\"\n type=\"text\"\n @keydown.down.prevent=\"moveActive(1)\"\n @keydown.enter.prevent=\"activeRef && toggleSelected(activeRef)\"\n @keydown.esc.prevent=\"close?.()\"\n @keydown.space=\"handleSpace\"\n @keydown.up.prevent=\"moveActive(-1)\" />\n </div>\n <ul\n v-show=\"filtered.length || slots.add || noResults\"\n :id=\"id\"\n :aria-multiselectable=\"multiselect\"\n class=\"border-t p-0.75 custom-scroll overscroll-contain flex-1 min-h-0\"\n role=\"listbox\"\n tabindex=\"-1\">\n <li\n v-if=\"!filtered.length && !slots.add && noResults\"\n class=\"text-c-3 px-2.5 py-2\"\n role=\"status\">\n {{ noResults }}\n </li>\n <ComboboxOptionGroup\n v-for=\"(group, i) in groups\"\n :id=\"`${id}-group-${i}`\"\n :key=\"i\"\n :hidden=\"\n // Only show the group label if there are some results\n !group.options.some((o) => filtered.some((f) => f.id === o.id)) ||\n // And it has a label\n !group.label\n \">\n <template #label>\n <slot\n v-if=\"$slots.group\"\n :group\n name=\"group\" />\n <template v-else>\n {{ group.label }}\n </template>\n </template>\n <template\n v-for=\"option in filtered\"\n :key=\"option.id\">\n <ComboboxOption\n v-if=\"group.options.some((o) => o.id === option.id)\"\n :id=\"getOptionId(option)\"\n v-slot=\"{ active, selected }\"\n :active=\"activeRef?.id === option.id\"\n :selected=\"model.some((o) => o.id === option.id)\"\n @click=\"toggleSelected(option)\"\n @mousedown.prevent\n @mouseenter=\"activeRef = option\">\n <slot\n v-if=\"$slots.option\"\n :active\n name=\"option\"\n :option\n :selected />\n <template v-else>\n <ScalarListboxCheckbox\n :multiselect\n :selected=\"model.some((o) => o.id === option.id)\" />\n <span class=\"inline-block min-w-0 flex-1 truncate text-c-1\">\n {{ option.label }}\n </span>\n </template>\n </ComboboxOption>\n </template>\n </ComboboxOptionGroup>\n <ComboboxOption\n v-if=\"slots.add\"\n :id=\"getOptionId(addOption)\"\n v-slot=\"{ active }\"\n :active=\"activeRef?.id === addOption.id\"\n @click=\"addNew\"\n @mousedown.prevent\n @mouseenter=\"activeRef = addOption\">\n <ScalarIconPlus class=\"size-4 p-px\" />\n <slot\n :active\n name=\"add\" />\n </ComboboxOption>\n </ul>\n</template>\n"],"mappings":""}
@@ -6,7 +6,7 @@ import { isGroups } from "./types.js";
6
6
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeModels, onMounted, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useId, useModel, useSlots, vModelText, vShow, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
7
7
  import { ScalarIconMagnifyingGlass, ScalarIconPlus } from "@scalar/icons";
8
8
  //#region src/components/ScalarCombobox/ScalarComboboxOptions.vue?vue&type=script&setup=true&lang.ts
9
- var _hoisted_1 = { class: "relative flex" };
9
+ var _hoisted_1 = { class: "relative flex m-1 mb-0.75" };
10
10
  var _hoisted_2 = [
11
11
  "aria-activedescendant",
12
12
  "aria-expanded",
@@ -120,7 +120,7 @@ var ScalarComboboxOptions_vue_vue_type_script_setup_true_lang_default = /*@__PUR
120
120
  const input = ref(null);
121
121
  onMounted(() => setTimeout(() => input.value?.focus(), 0));
122
122
  return (_ctx, _cache) => {
123
- return openBlock(), createElementBlock(Fragment, null, [createElementVNode("div", _hoisted_1, [createVNode(unref(ScalarIconMagnifyingGlass), { class: "pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-c-3 size-4" }), withDirectives(createElementVNode("input", {
123
+ return openBlock(), createElementBlock(Fragment, null, [createElementVNode("div", _hoisted_1, [createVNode(unref(ScalarIconMagnifyingGlass), { class: "pointer-events-none absolute left-1.75 top-1/2 -translate-y-1/2 text-c-3 size-4" }), withDirectives(createElementVNode("input", {
124
124
  ref_key: "input",
125
125
  ref: input,
126
126
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => query.value = $event),
@@ -129,7 +129,7 @@ var ScalarComboboxOptions_vue_vue_type_script_setup_true_lang_default = /*@__PUR
129
129
  "aria-controls": id,
130
130
  "aria-expanded": Boolean(filtered.value.length || slots.add || __props.noResults),
131
131
  "aria-label": __props.inputLabel,
132
- class: "min-w-0 flex-1 rounded border-0 py-2.5 pl-8 pr-3 leading-none text-c-1 -outline-offset-1",
132
+ class: "min-w-0 flex-1 rounded-md border-0 py-1.5 pl-7.25 pr-1.75 leading-none text-c-1",
133
133
  "data-1p-ignore": "",
134
134
  placeholder: __props.placeholder,
135
135
  role: "combobox",
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarComboboxOptions.vue.script.js","names":["$slots"],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxOptions.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Options component\n *\n * Renders the searchable option list for a combobox, including\n * filtering, keyboard navigation, and an optional \"add new\" action.\n *\n * @example\n * <ScalarComboboxOptions v-model=\"selected\" :options=\"options\" />\n */\nexport default {}\n</script>\n\n<!-- prettier-ignore-attribute generic -->\n<script\n setup\n lang=\"ts\"\n generic=\"O extends Option = Option, G extends OptionGroup<O> = OptionGroup<O>\">\nimport { filterByOptionLabel } from '@/components/ScalarCombobox/filter-by-option-label'\nimport { ScalarIconMagnifyingGlass, ScalarIconPlus } from '@scalar/icons'\nimport { computed, onMounted, ref, useId, watch } from 'vue'\n\nimport { ScalarListboxCheckbox } from '../ScalarListbox'\nimport ComboboxOption from './ScalarComboboxOption.vue'\nimport ComboboxOptionGroup from './ScalarComboboxOptionGroup.vue'\nimport {\n type ComboboxEmits,\n type ComboboxSlots,\n type FilterFunction,\n type Option,\n type OptionGroup,\n type OptionsOrGroups,\n isGroups,\n} from './types'\n\nconst {\n options: optionsOrGroups,\n placeholder,\n inputLabel,\n noResults,\n close,\n filterFn = filterByOptionLabel,\n multiselect,\n} = defineProps<{\n /** The options to display in the combobox */\n options: OptionsOrGroups<O, G>\n /** The placeholder text to display in the combobox */\n placeholder?: string\n /** An accessible label for the search input */\n inputLabel?: string\n /** The message to display when filtering returns no options */\n noResults?: string\n /** Close the popover without changing the current selection */\n close?: () => void\n /**\n * A function to filter the options based on a query,\n * if not provided, the options will be filtered by option label\n *\n * @see {@link FilterFunction} for more information\n */\n filterFn?: FilterFunction<O, G>\n /** Whether the combobox is in multiselect mode, defaults to false */\n multiselect?: boolean\n}>()\n\nconst emit = defineEmits<ComboboxEmits>()\n\nconst model = defineModel<O[]>({ default: () => [] })\n\nconst slots = defineSlots<Omit<ComboboxSlots<O, G>, 'default'>>()\n\ndefineOptions({ inheritAttrs: false })\n\n/** A unique ID for the combobox */\nconst id = `scalar-combobox-items-${useId()}`\n\n/** A static option entry for the \"Add a new option\" option */\nconst addOption: Option = { id: `${useId()}-add`, label: 'Add a new option' }\n\n/** Generate a unique ID for an option */\nfunction getOptionId(option: Option) {\n return `${id}-${option.id}`\n}\n\n/** A flat list of all options */\nconst options = computed<O[]>(() =>\n isGroups(optionsOrGroups)\n ? optionsOrGroups.flatMap((group) => group.options)\n : optionsOrGroups,\n)\n\n/** An list of all groups */\nconst groups = computed<G[]>(\n () =>\n isGroups(optionsOrGroups)\n ? optionsOrGroups // G extends OptionGroup<O>\n : /*\n We know G is an unextended OptionGroup<O> here because of the\n structure of the component props so we can cast it to G\n */\n [{ label: '', options: optionsOrGroups } as G], // G is OptionGroup<O>\n)\n\nconst query = ref<string>('')\nconst activeRef = ref<Option | undefined>(model.value?.[0] ?? options.value[0])\n\n// Clear the query on open and close\nonMounted(() => {\n // Clear the query\n query.value = ''\n\n // Set the active option to the selected option or the first option\n activeRef.value = model.value?.[0] ?? options.value[0]\n\n // Scroll to the selected option\n const selected = model.value[0]\n if (selected) {\n setTimeout(() => {\n const value = model.value[0]\n if (!value) {\n return\n }\n\n document\n ?.getElementById(getOptionId(value))\n ?.scrollIntoView({ block: 'nearest' })\n }, 10)\n }\n})\n\n// Set the top option as active when searching\nwatch(\n () => query.value,\n () => (activeRef.value = withAdd.value[0]),\n)\n\n/** The filtered list of options */\nconst filtered = computed<O[]>(() =>\n filterFn(query.value, options.value, groups.value),\n)\n\n/** The list of filtered options with the \"Add a new option\" option */\nconst withAdd = computed<Option[]>(() =>\n slots.add ? [...filtered.value, addOption] : filtered.value,\n)\n\nfunction toggleSelected(option: Option | undefined) {\n if (!option) {\n return\n }\n\n if (option.id === addOption.id) {\n addNew()\n return\n }\n\n if (multiselect) {\n // Remove from selection list\n if (model.value.some((o) => o.id === option.id)) {\n model.value = model.value.filter((o) => o.id !== option.id)\n }\n // Add to selection list\n else {\n model.value = [\n ...model.value,\n options.value.find((o) => o.id === option.id)!,\n ]\n }\n } else {\n // Set selection for single select mode\n model.value = [options.value.find((o) => o.id === option.id)!]\n }\n}\n\nfunction moveActive(dir: 1 | -1) {\n const list = withAdd.value\n\n // Find active index\n const activeIdx = list.findIndex(\n (option) => option.id === activeRef.value?.id,\n )\n\n // Calculate next index and exit if it's out of bounds\n const nextIdx = activeIdx + dir\n\n if (nextIdx < 0 || nextIdx > list.length - 1) {\n return\n }\n\n activeRef.value = list[nextIdx]! // We know it's in bounds from the check above\n\n if (!activeRef.value) {\n return\n }\n\n // Scroll to the active option\n document?.getElementById(getOptionId(activeRef.value))?.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n })\n}\n\nfunction addNew() {\n emit('add')\n query.value = ''\n}\n\n/**\n * Space toggles the active option in multiselect mode while the search box is empty.\n *\n * The options look like checkboxes, so keyboard users press Space to toggle them. Without this\n * handler Space types a leading space into the query, which filters out every option whose label\n * has no space and hides the whole list without any feedback (found by an accessibility audit).\n * Once a query has been typed, Space keeps inserting a character so multi-word labels stay\n * searchable. Key auto-repeat is ignored so holding Space after opening the popover with it does\n * not toggle the option repeatedly, and IME composition is left alone.\n */\nconst handleSpace = (event: KeyboardEvent): void => {\n if (!multiselect || query.value !== '' || event.isComposing) {\n return\n }\n // Suppress repeated spaces too, so holding the key does not start filtering.\n event.preventDefault()\n if (!event.repeat) {\n toggleSelected(activeRef.value)\n }\n}\n\n// Manual autofocus for the input\nconst input = ref<HTMLInputElement | null>(null)\n\n// This must be a setTimeout to ensure there is no scroll jump. nextTick does not work here.\nonMounted(() => setTimeout(() => input.value?.focus(), 0))\n</script>\n<template>\n <div class=\"relative flex\">\n <ScalarIconMagnifyingGlass\n class=\"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-c-3 size-4\" />\n <input\n ref=\"input\"\n v-model=\"query\"\n :aria-activedescendant=\"activeRef ? getOptionId(activeRef) : undefined\"\n aria-autocomplete=\"list\"\n :aria-controls=\"id\"\n :aria-expanded=\"Boolean(filtered.length || slots.add || noResults)\"\n :aria-label=\"inputLabel\"\n class=\"min-w-0 flex-1 rounded border-0 py-2.5 pl-8 pr-3 leading-none text-c-1 -outline-offset-1\"\n data-1p-ignore\n :placeholder\n role=\"combobox\"\n tabindex=\"0\"\n type=\"text\"\n @keydown.down.prevent=\"moveActive(1)\"\n @keydown.enter.prevent=\"activeRef && toggleSelected(activeRef)\"\n @keydown.esc.prevent=\"close?.()\"\n @keydown.space=\"handleSpace\"\n @keydown.up.prevent=\"moveActive(-1)\" />\n </div>\n <ul\n v-show=\"filtered.length || slots.add || noResults\"\n :id=\"id\"\n :aria-multiselectable=\"multiselect\"\n class=\"border-t p-0.75 custom-scroll overscroll-contain flex-1 min-h-0\"\n role=\"listbox\"\n tabindex=\"-1\">\n <li\n v-if=\"!filtered.length && !slots.add && noResults\"\n class=\"text-c-3 px-2.5 py-2\"\n role=\"status\">\n {{ noResults }}\n </li>\n <ComboboxOptionGroup\n v-for=\"(group, i) in groups\"\n :id=\"`${id}-group-${i}`\"\n :key=\"i\"\n :hidden=\"\n // Only show the group label if there are some results\n !group.options.some((o) => filtered.some((f) => f.id === o.id)) ||\n // And it has a label\n !group.label\n \">\n <template #label>\n <slot\n v-if=\"$slots.group\"\n :group\n name=\"group\" />\n <template v-else>\n {{ group.label }}\n </template>\n </template>\n <template\n v-for=\"option in filtered\"\n :key=\"option.id\">\n <ComboboxOption\n v-if=\"group.options.some((o) => o.id === option.id)\"\n :id=\"getOptionId(option)\"\n v-slot=\"{ active, selected }\"\n :active=\"activeRef?.id === option.id\"\n :selected=\"model.some((o) => o.id === option.id)\"\n @click=\"toggleSelected(option)\"\n @mousedown.prevent\n @mouseenter=\"activeRef = option\">\n <slot\n v-if=\"$slots.option\"\n :active\n name=\"option\"\n :option\n :selected />\n <template v-else>\n <ScalarListboxCheckbox\n :multiselect\n :selected=\"model.some((o) => o.id === option.id)\" />\n <span class=\"inline-block min-w-0 flex-1 truncate text-c-1\">\n {{ option.label }}\n </span>\n </template>\n </ComboboxOption>\n </template>\n </ComboboxOptionGroup>\n <ComboboxOption\n v-if=\"slots.add\"\n :id=\"getOptionId(addOption)\"\n v-slot=\"{ active }\"\n :active=\"activeRef?.id === addOption.id\"\n @click=\"addNew\"\n @mousedown.prevent\n @mouseenter=\"activeRef = addOption\">\n <ScalarIconPlus class=\"size-4 p-px\" />\n <slot\n :active\n name=\"add\" />\n </ComboboxOption>\n </ul>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"ScalarComboboxOptions.vue.script.js","names":["$slots"],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxOptions.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Options component\n *\n * Renders the searchable option list for a combobox, including\n * filtering, keyboard navigation, and an optional \"add new\" action.\n *\n * @example\n * <ScalarComboboxOptions v-model=\"selected\" :options=\"options\" />\n */\nexport default {}\n</script>\n\n<!-- prettier-ignore-attribute generic -->\n<script\n setup\n lang=\"ts\"\n generic=\"O extends Option = Option, G extends OptionGroup<O> = OptionGroup<O>\">\nimport { filterByOptionLabel } from '@/components/ScalarCombobox/filter-by-option-label'\nimport { ScalarIconMagnifyingGlass, ScalarIconPlus } from '@scalar/icons'\nimport { computed, onMounted, ref, useId, watch } from 'vue'\n\nimport { ScalarListboxCheckbox } from '../ScalarListbox'\nimport ComboboxOption from './ScalarComboboxOption.vue'\nimport ComboboxOptionGroup from './ScalarComboboxOptionGroup.vue'\nimport {\n type ComboboxEmits,\n type ComboboxSlots,\n type FilterFunction,\n type Option,\n type OptionGroup,\n type OptionsOrGroups,\n isGroups,\n} from './types'\n\nconst {\n options: optionsOrGroups,\n placeholder,\n inputLabel,\n noResults,\n close,\n filterFn = filterByOptionLabel,\n multiselect,\n} = defineProps<{\n /** The options to display in the combobox */\n options: OptionsOrGroups<O, G>\n /** The placeholder text to display in the combobox */\n placeholder?: string\n /** An accessible label for the search input */\n inputLabel?: string\n /** The message to display when filtering returns no options */\n noResults?: string\n /** Close the popover without changing the current selection */\n close?: () => void\n /**\n * A function to filter the options based on a query,\n * if not provided, the options will be filtered by option label\n *\n * @see {@link FilterFunction} for more information\n */\n filterFn?: FilterFunction<O, G>\n /** Whether the combobox is in multiselect mode, defaults to false */\n multiselect?: boolean\n}>()\n\nconst emit = defineEmits<ComboboxEmits>()\n\nconst model = defineModel<O[]>({ default: () => [] })\n\nconst slots = defineSlots<Omit<ComboboxSlots<O, G>, 'default'>>()\n\ndefineOptions({ inheritAttrs: false })\n\n/** A unique ID for the combobox */\nconst id = `scalar-combobox-items-${useId()}`\n\n/** A static option entry for the \"Add a new option\" option */\nconst addOption: Option = { id: `${useId()}-add`, label: 'Add a new option' }\n\n/** Generate a unique ID for an option */\nfunction getOptionId(option: Option) {\n return `${id}-${option.id}`\n}\n\n/** A flat list of all options */\nconst options = computed<O[]>(() =>\n isGroups(optionsOrGroups)\n ? optionsOrGroups.flatMap((group) => group.options)\n : optionsOrGroups,\n)\n\n/** An list of all groups */\nconst groups = computed<G[]>(\n () =>\n isGroups(optionsOrGroups)\n ? optionsOrGroups // G extends OptionGroup<O>\n : /*\n We know G is an unextended OptionGroup<O> here because of the\n structure of the component props so we can cast it to G\n */\n [{ label: '', options: optionsOrGroups } as G], // G is OptionGroup<O>\n)\n\nconst query = ref<string>('')\nconst activeRef = ref<Option | undefined>(model.value?.[0] ?? options.value[0])\n\n// Clear the query on open and close\nonMounted(() => {\n // Clear the query\n query.value = ''\n\n // Set the active option to the selected option or the first option\n activeRef.value = model.value?.[0] ?? options.value[0]\n\n // Scroll to the selected option\n const selected = model.value[0]\n if (selected) {\n setTimeout(() => {\n const value = model.value[0]\n if (!value) {\n return\n }\n\n document\n ?.getElementById(getOptionId(value))\n ?.scrollIntoView({ block: 'nearest' })\n }, 10)\n }\n})\n\n// Set the top option as active when searching\nwatch(\n () => query.value,\n () => (activeRef.value = withAdd.value[0]),\n)\n\n/** The filtered list of options */\nconst filtered = computed<O[]>(() =>\n filterFn(query.value, options.value, groups.value),\n)\n\n/** The list of filtered options with the \"Add a new option\" option */\nconst withAdd = computed<Option[]>(() =>\n slots.add ? [...filtered.value, addOption] : filtered.value,\n)\n\nfunction toggleSelected(option: Option | undefined) {\n if (!option) {\n return\n }\n\n if (option.id === addOption.id) {\n addNew()\n return\n }\n\n if (multiselect) {\n // Remove from selection list\n if (model.value.some((o) => o.id === option.id)) {\n model.value = model.value.filter((o) => o.id !== option.id)\n }\n // Add to selection list\n else {\n model.value = [\n ...model.value,\n options.value.find((o) => o.id === option.id)!,\n ]\n }\n } else {\n // Set selection for single select mode\n model.value = [options.value.find((o) => o.id === option.id)!]\n }\n}\n\nfunction moveActive(dir: 1 | -1) {\n const list = withAdd.value\n\n // Find active index\n const activeIdx = list.findIndex(\n (option) => option.id === activeRef.value?.id,\n )\n\n // Calculate next index and exit if it's out of bounds\n const nextIdx = activeIdx + dir\n\n if (nextIdx < 0 || nextIdx > list.length - 1) {\n return\n }\n\n activeRef.value = list[nextIdx]! // We know it's in bounds from the check above\n\n if (!activeRef.value) {\n return\n }\n\n // Scroll to the active option\n document?.getElementById(getOptionId(activeRef.value))?.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n })\n}\n\nfunction addNew() {\n emit('add')\n query.value = ''\n}\n\n/**\n * Space toggles the active option in multiselect mode while the search box is empty.\n *\n * The options look like checkboxes, so keyboard users press Space to toggle them. Without this\n * handler Space types a leading space into the query, which filters out every option whose label\n * has no space and hides the whole list without any feedback (found by an accessibility audit).\n * Once a query has been typed, Space keeps inserting a character so multi-word labels stay\n * searchable. Key auto-repeat is ignored so holding Space after opening the popover with it does\n * not toggle the option repeatedly, and IME composition is left alone.\n */\nconst handleSpace = (event: KeyboardEvent): void => {\n if (!multiselect || query.value !== '' || event.isComposing) {\n return\n }\n // Suppress repeated spaces too, so holding the key does not start filtering.\n event.preventDefault()\n if (!event.repeat) {\n toggleSelected(activeRef.value)\n }\n}\n\n// Manual autofocus for the input\nconst input = ref<HTMLInputElement | null>(null)\n\n// This must be a setTimeout to ensure there is no scroll jump. nextTick does not work here.\nonMounted(() => setTimeout(() => input.value?.focus(), 0))\n</script>\n<template>\n <!-- Inset to line up with the options below -->\n <div class=\"relative flex m-1 mb-0.75\">\n <ScalarIconMagnifyingGlass\n class=\"pointer-events-none absolute left-1.75 top-1/2 -translate-y-1/2 text-c-3 size-4\" />\n <input\n ref=\"input\"\n v-model=\"query\"\n :aria-activedescendant=\"activeRef ? getOptionId(activeRef) : undefined\"\n aria-autocomplete=\"list\"\n :aria-controls=\"id\"\n :aria-expanded=\"Boolean(filtered.length || slots.add || noResults)\"\n :aria-label=\"inputLabel\"\n class=\"min-w-0 flex-1 rounded-md border-0 py-1.5 pl-7.25 pr-1.75 leading-none text-c-1\"\n data-1p-ignore\n :placeholder\n role=\"combobox\"\n tabindex=\"0\"\n type=\"text\"\n @keydown.down.prevent=\"moveActive(1)\"\n @keydown.enter.prevent=\"activeRef && toggleSelected(activeRef)\"\n @keydown.esc.prevent=\"close?.()\"\n @keydown.space=\"handleSpace\"\n @keydown.up.prevent=\"moveActive(-1)\" />\n </div>\n <ul\n v-show=\"filtered.length || slots.add || noResults\"\n :id=\"id\"\n :aria-multiselectable=\"multiselect\"\n class=\"border-t p-0.75 custom-scroll overscroll-contain flex-1 min-h-0\"\n role=\"listbox\"\n tabindex=\"-1\">\n <li\n v-if=\"!filtered.length && !slots.add && noResults\"\n class=\"text-c-3 px-2.5 py-2\"\n role=\"status\">\n {{ noResults }}\n </li>\n <ComboboxOptionGroup\n v-for=\"(group, i) in groups\"\n :id=\"`${id}-group-${i}`\"\n :key=\"i\"\n :hidden=\"\n // Only show the group label if there are some results\n !group.options.some((o) => filtered.some((f) => f.id === o.id)) ||\n // And it has a label\n !group.label\n \">\n <template #label>\n <slot\n v-if=\"$slots.group\"\n :group\n name=\"group\" />\n <template v-else>\n {{ group.label }}\n </template>\n </template>\n <template\n v-for=\"option in filtered\"\n :key=\"option.id\">\n <ComboboxOption\n v-if=\"group.options.some((o) => o.id === option.id)\"\n :id=\"getOptionId(option)\"\n v-slot=\"{ active, selected }\"\n :active=\"activeRef?.id === option.id\"\n :selected=\"model.some((o) => o.id === option.id)\"\n @click=\"toggleSelected(option)\"\n @mousedown.prevent\n @mouseenter=\"activeRef = option\">\n <slot\n v-if=\"$slots.option\"\n :active\n name=\"option\"\n :option\n :selected />\n <template v-else>\n <ScalarListboxCheckbox\n :multiselect\n :selected=\"model.some((o) => o.id === option.id)\" />\n <span class=\"inline-block min-w-0 flex-1 truncate text-c-1\">\n {{ option.label }}\n </span>\n </template>\n </ComboboxOption>\n </template>\n </ComboboxOptionGroup>\n <ComboboxOption\n v-if=\"slots.add\"\n :id=\"getOptionId(addOption)\"\n v-slot=\"{ active }\"\n :active=\"activeRef?.id === addOption.id\"\n @click=\"addNew\"\n @mousedown.prevent\n @mouseenter=\"activeRef = addOption\">\n <ScalarIconPlus class=\"size-4 p-px\" />\n <slot\n :active\n name=\"add\" />\n </ComboboxOption>\n </ul>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarComboboxPopover.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarCombobox/ScalarComboboxPopover.vue"],"names":[],"mappings":"AAsFA,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAG1D;;;;;;;;;;;GAWG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mRAsKd,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"ScalarComboboxPopover.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarCombobox/ScalarComboboxPopover.vue"],"names":[],"mappings":"AAmFA,OAAO,EAAkB,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAC9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAG1D;;;;;;;;;;;GAWG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mRAiKd,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarComboboxPopover.vue.js","names":[],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxPopover.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Popover component\n *\n * Wraps combobox content in a floating popover panel.\n * Handles open/close behavior and keyboard interactions.\n *\n * @example\n * <ScalarComboboxPopover>\n * <button>Toggle</button>\n * <template #popover=\"{ close }\">Content</template>\n * </ScalarComboboxPopover>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\nimport { ref } from 'vue'\n\nimport {\n ScalarFloating,\n ScalarFloatingBackdrop,\n type ScalarFloatingOptions,\n} from '../ScalarFloating'\nimport type { ScalarPopoverSlots } from '../ScalarPopover'\n\ndefineProps<ScalarFloatingOptions>()\n\ndefineSlots<ScalarPopoverSlots>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n\n/** Expose the popover button so we can close the popup */\nconst popoverButtonRef = ref<typeof PopoverButton | null>(null)\n\n/** Open the popover of the up or down arrows are pressed */\nconst handleKeydown = (e: KeyboardEvent) => {\n if (!['ArrowUp', 'ArrowDown'].includes(e.key)) {\n return\n }\n e.preventDefault()\n e.target?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))\n}\n\ndefineExpose({ popoverButtonRef })\n</script>\n<template>\n <Popover\n v-slot=\"{ open }\"\n as=\"template\">\n <ScalarFloating v-bind=\"$props\">\n <PopoverButton\n ref=\"popoverButtonRef\"\n as=\"template\"\n @keydown=\"handleKeydown\">\n <slot :open />\n </PopoverButton>\n <template\n v-if=\"open\"\n #floating=\"{ width }\">\n <PopoverPanel\n v-slot=\"{ close }\"\n :style=\"{ width }\"\n v-bind=\"\n cx('relative flex flex-col max-h-[inherit] w-40 rounded text-sm')\n \">\n <slot\n :close\n name=\"popover\"\n :open />\n <ScalarFloatingBackdrop />\n </PopoverPanel>\n </template>\n </ScalarFloating>\n </Popover>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ScalarComboboxPopover.vue.js","names":[],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxPopover.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Popover component\n *\n * Wraps combobox content in a floating popover panel.\n * Handles open/close behavior and keyboard interactions.\n *\n * @example\n * <ScalarComboboxPopover>\n * <button>Toggle</button>\n * <template #popover=\"{ close }\">Content</template>\n * </ScalarComboboxPopover>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\nimport { ref } from 'vue'\n\nimport { ScalarFloating, type ScalarFloatingOptions } from '../ScalarFloating'\nimport type { ScalarPopoverSlots } from '../ScalarPopover'\n\ndefineProps<ScalarFloatingOptions>()\n\ndefineSlots<ScalarPopoverSlots>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n\n/** Expose the popover button so we can close the popup */\nconst popoverButtonRef = ref<typeof PopoverButton | null>(null)\n\n/** Open the popover of the up or down arrows are pressed */\nconst handleKeydown = (e: KeyboardEvent) => {\n if (!['ArrowUp', 'ArrowDown'].includes(e.key)) {\n return\n }\n e.preventDefault()\n e.target?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))\n}\n\ndefineExpose({ popoverButtonRef })\n</script>\n<template>\n <Popover\n v-slot=\"{ open }\"\n as=\"template\">\n <ScalarFloating v-bind=\"$props\">\n <PopoverButton\n ref=\"popoverButtonRef\"\n as=\"template\"\n @keydown=\"handleKeydown\">\n <slot :open />\n </PopoverButton>\n <template\n v-if=\"open\"\n #floating=\"{ width }\">\n <PopoverPanel\n v-slot=\"{ close }\"\n :style=\"{ width }\"\n v-bind=\"\n cx(\n 'relative flex flex-col max-h-[inherit] w-40 rounded-xl bg-b-1 dark:bg-b-1.5 text-sm shadow-md inset-shadow-border',\n )\n \">\n <slot\n :close\n name=\"popover\"\n :open />\n </PopoverPanel>\n </template>\n </ScalarFloating>\n </Popover>\n</template>\n"],"mappings":""}
@@ -1,5 +1,4 @@
1
1
  import ScalarFloating_default from "../ScalarFloating/ScalarFloating.vue.js";
2
- import ScalarFloatingBackdrop_default from "../ScalarFloating/ScalarFloatingBackdrop.vue.js";
3
2
  import { useBindCx } from "@scalar/use-hooks/useBindCx";
4
3
  import { createBlock, createSlots, createVNode, defineComponent, guardReactiveProps, mergeProps, normalizeProps, openBlock, ref, renderSlot, unref, withCtx } from "vue";
5
4
  import { Popover, PopoverButton, PopoverPanel } from "@headlessui/vue";
@@ -44,11 +43,11 @@ var ScalarComboboxPopover_vue_vue_type_script_setup_true_lang_default = /*@__PUR
44
43
  _: 2
45
44
  }, [open ? {
46
45
  name: "floating",
47
- fn: withCtx(({ width }) => [createVNode(unref(PopoverPanel), mergeProps({ style: { width } }, unref(cx)("relative flex flex-col max-h-[inherit] w-40 rounded text-sm")), {
46
+ fn: withCtx(({ width }) => [createVNode(unref(PopoverPanel), mergeProps({ style: { width } }, unref(cx)("relative flex flex-col max-h-[inherit] w-40 rounded-xl bg-b-1 dark:bg-b-1.5 text-sm shadow-md inset-shadow-border")), {
48
47
  default: withCtx(({ close }) => [renderSlot(_ctx.$slots, "popover", {
49
48
  close,
50
49
  open
51
- }), createVNode(unref(ScalarFloatingBackdrop_default))]),
50
+ })]),
52
51
  _: 2
53
52
  }, 1040, ["style"])]),
54
53
  key: "0"
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarComboboxPopover.vue.script.js","names":["$props"],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxPopover.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Popover component\n *\n * Wraps combobox content in a floating popover panel.\n * Handles open/close behavior and keyboard interactions.\n *\n * @example\n * <ScalarComboboxPopover>\n * <button>Toggle</button>\n * <template #popover=\"{ close }\">Content</template>\n * </ScalarComboboxPopover>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\nimport { ref } from 'vue'\n\nimport {\n ScalarFloating,\n ScalarFloatingBackdrop,\n type ScalarFloatingOptions,\n} from '../ScalarFloating'\nimport type { ScalarPopoverSlots } from '../ScalarPopover'\n\ndefineProps<ScalarFloatingOptions>()\n\ndefineSlots<ScalarPopoverSlots>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n\n/** Expose the popover button so we can close the popup */\nconst popoverButtonRef = ref<typeof PopoverButton | null>(null)\n\n/** Open the popover of the up or down arrows are pressed */\nconst handleKeydown = (e: KeyboardEvent) => {\n if (!['ArrowUp', 'ArrowDown'].includes(e.key)) {\n return\n }\n e.preventDefault()\n e.target?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))\n}\n\ndefineExpose({ popoverButtonRef })\n</script>\n<template>\n <Popover\n v-slot=\"{ open }\"\n as=\"template\">\n <ScalarFloating v-bind=\"$props\">\n <PopoverButton\n ref=\"popoverButtonRef\"\n as=\"template\"\n @keydown=\"handleKeydown\">\n <slot :open />\n </PopoverButton>\n <template\n v-if=\"open\"\n #floating=\"{ width }\">\n <PopoverPanel\n v-slot=\"{ close }\"\n :style=\"{ width }\"\n v-bind=\"\n cx('relative flex flex-col max-h-[inherit] w-40 rounded text-sm')\n \">\n <slot\n :close\n name=\"popover\"\n :open />\n <ScalarFloatingBackdrop />\n </PopoverPanel>\n </template>\n </ScalarFloating>\n </Popover>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAiCA,MAAM,EAAE,OAAO,UAAU;;EAGzB,MAAM,mBAAmB,IAAiC,IAAI;;EAG9D,MAAM,iBAAiB,MAAqB;GAC1C,IAAI,CAAC,CAAC,WAAW,WAAW,CAAC,CAAC,SAAS,EAAE,GAAG,GAC1C;GAEF,EAAE,eAAe;GACjB,EAAE,QAAQ,cAAc,IAAI,cAAc,WAAW,EAAE,KAAK,QAAQ,CAAC,CAAC;EACxE;EAEA,SAAa,EAAE,iBAAiB,CAAC;;uBAG/B,YA2BU,MAAA,OAAA,GAAA,EAzBR,IAAG,WAAU,GAAA;sBAwBI,EAzBP,WAAI,CAEd,YAuBiB,MAAA,sBAAA,GAAA,eAAA,mBAvBOA,KAAAA,MAAM,CAAA,GAAA,YAAA;4BAMZ,CALhB,YAKgB,MAAA,aAAA,GAAA;eAJV;MAAJ,KAAI;MACJ,IAAG;MACF,WAAS;;6BACI,CAAd,WAAc,KAAA,QAAA,WAAA,EAAP,KAAI,CAAA,CAAA,CAAA;;;;QAGL,OAAA;WACL;kBAYc,EAZF,YAAK,CAClB,YAWe,MAAA,YAAA,GAXf,WAWe,EATZ,OAAK,EAAI,MAAK,EAAA,GACM,MAAA,EAAA,CAAE,CAAA,6DAAA,CAAA,GAAA;wBAMb,EARA,YAAK,CAKf,WAGU,KAAA,QAAA,WAAA;OAFP;OAEA;UACH,YAA0B,MAAA,8BAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"ScalarComboboxPopover.vue.script.js","names":["$props"],"sources":["../../../src/components/ScalarCombobox/ScalarComboboxPopover.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Combobox Popover component\n *\n * Wraps combobox content in a floating popover panel.\n * Handles open/close behavior and keyboard interactions.\n *\n * @example\n * <ScalarComboboxPopover>\n * <button>Toggle</button>\n * <template #popover=\"{ close }\">Content</template>\n * </ScalarComboboxPopover>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\nimport { ref } from 'vue'\n\nimport { ScalarFloating, type ScalarFloatingOptions } from '../ScalarFloating'\nimport type { ScalarPopoverSlots } from '../ScalarPopover'\n\ndefineProps<ScalarFloatingOptions>()\n\ndefineSlots<ScalarPopoverSlots>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n\n/** Expose the popover button so we can close the popup */\nconst popoverButtonRef = ref<typeof PopoverButton | null>(null)\n\n/** Open the popover of the up or down arrows are pressed */\nconst handleKeydown = (e: KeyboardEvent) => {\n if (!['ArrowUp', 'ArrowDown'].includes(e.key)) {\n return\n }\n e.preventDefault()\n e.target?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))\n}\n\ndefineExpose({ popoverButtonRef })\n</script>\n<template>\n <Popover\n v-slot=\"{ open }\"\n as=\"template\">\n <ScalarFloating v-bind=\"$props\">\n <PopoverButton\n ref=\"popoverButtonRef\"\n as=\"template\"\n @keydown=\"handleKeydown\">\n <slot :open />\n </PopoverButton>\n <template\n v-if=\"open\"\n #floating=\"{ width }\">\n <PopoverPanel\n v-slot=\"{ close }\"\n :style=\"{ width }\"\n v-bind=\"\n cx(\n 'relative flex flex-col max-h-[inherit] w-40 rounded-xl bg-b-1 dark:bg-b-1.5 text-sm shadow-md inset-shadow-border',\n )\n \">\n <slot\n :close\n name=\"popover\"\n :open />\n </PopoverPanel>\n </template>\n </ScalarFloating>\n </Popover>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EA6BA,MAAM,EAAE,OAAO,UAAU;;EAGzB,MAAM,mBAAmB,IAAiC,IAAI;;EAG9D,MAAM,iBAAiB,MAAqB;GAC1C,IAAI,CAAC,CAAC,WAAW,WAAW,CAAC,CAAC,SAAS,EAAE,GAAG,GAC1C;GAEF,EAAE,eAAe;GACjB,EAAE,QAAQ,cAAc,IAAI,cAAc,WAAW,EAAE,KAAK,QAAQ,CAAC,CAAC;EACxE;EAEA,SAAa,EAAE,iBAAiB,CAAC;;uBAG/B,YA4BU,MAAA,OAAA,GAAA,EA1BR,IAAG,WAAU,GAAA;sBAyBI,EA1BP,WAAI,CAEd,YAwBiB,MAAA,sBAAA,GAAA,eAAA,mBAxBOA,KAAAA,MAAM,CAAA,GAAA,YAAA;4BAMZ,CALhB,YAKgB,MAAA,aAAA,GAAA;eAJV;MAAJ,KAAI;MACJ,IAAG;MACF,WAAS;;6BACI,CAAd,WAAc,KAAA,QAAA,WAAA,EAAP,KAAI,CAAA,CAAA,CAAA;;;;QAGL,OAAA;WACL;kBAac,EAbF,YAAK,CAClB,YAYe,MAAA,YAAA,GAZf,WAYe,EAVZ,OAAK,EAAI,MAAK,EAAA,GACM,MAAA,EAAA,CAAE,CAAA,mHAAA,CAAA,GAAA;wBAQb,EAVA,YAAK,CAOf,WAGU,KAAA,QAAA,WAAA;OAFP;OAEA"}
@@ -27,8 +27,6 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
27
27
  default?(): unknown;
28
28
  /** Overrides the normal menu list element */
29
29
  menu?(): unknown;
30
- /** Overrides the backdrop for the dropdown */
31
- backdrop?(): unknown;
32
30
  }>;
33
31
  type __VLS_WithSlots<T, S> = T & {
34
32
  new (): {
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarDropdownMenu.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarDropdown/ScalarDropdownMenu.vue"],"names":[],"mappings":"AAgEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,KAAK,CAAA;AAKpC;;;;;;;;;;;;;;GAcG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;IAEhB,8BAA8B;SACzB,MAAM,GAAG,SAAS;;IADvB,8BAA8B;SACzB,MAAM,GAAG,SAAS;;IAKvB,wBAAwB;gBACZ,OAAO;IACnB,6CAA6C;aACpC,OAAO;IAChB,8CAA8C;iBACjC,OAAO;EA6ElB,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"ScalarDropdownMenu.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarDropdown/ScalarDropdownMenu.vue"],"names":[],"mappings":"AA6DA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,KAAK,CAAA;AAGpC;;;;;;;;;;;;;;GAcG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;IAEhB,8BAA8B;SACzB,MAAM,GAAG,SAAS;;IADvB,8BAA8B;SACzB,MAAM,GAAG,SAAS;;IAKvB,wBAAwB;gBACZ,OAAO;IACnB,6CAA6C;aACpC,OAAO;EAsEd,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarDropdownMenu.vue.js","names":[],"sources":["../../../src/components/ScalarDropdown/ScalarDropdownMenu.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar dropdown menu component\n *\n * Provides a scrollable container for dropdown items\n * This is used internally by the ScalarDropdown component\n *\n * If you're looking to create a dropdown menu with a trigger\n * button you probably want the ScalarDropdown component\n *\n * @example\n * <ScalarDropdownMenu>\n * <ScalarDropdownItem>Item 1</ScalarDropdownItem>\n * <ScalarDropdownItem>Item 2</ScalarDropdownItem>\n * </ScalarDropdownMenu>\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\nimport { type Component } from 'vue'\n\nimport { ScalarFloatingBackdrop } from '../ScalarFloating'\n\ndefineProps<{\n /** The component to render */\n is?: string | Component\n}>()\n\ndefineSlots<{\n /** The menu contents */\n default?(): unknown\n /** Overrides the normal menu list element */\n menu?(): unknown\n /** Overrides the backdrop for the dropdown */\n backdrop?(): unknown\n}>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <!-- Background container -->\n <component\n :is=\"is ?? 'div'\"\n v-bind=\"cx('relative flex w-56')\">\n <!-- Scroll container -->\n <div class=\"custom-scroll min-h-0 flex-1\">\n <!-- Menu items -->\n <slot name=\"menu\">\n <div class=\"flex flex-col p-0.75\">\n <slot />\n </div>\n </slot>\n <slot name=\"backdrop\">\n <ScalarFloatingBackdrop class=\"rounded-xl border shadow-md\" />\n </slot>\n </div>\n </component>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ScalarDropdownMenu.vue.js","names":[],"sources":["../../../src/components/ScalarDropdown/ScalarDropdownMenu.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar dropdown menu component\n *\n * Provides a scrollable container for dropdown items\n * This is used internally by the ScalarDropdown component\n *\n * If you're looking to create a dropdown menu with a trigger\n * button you probably want the ScalarDropdown component\n *\n * @example\n * <ScalarDropdownMenu>\n * <ScalarDropdownItem>Item 1</ScalarDropdownItem>\n * <ScalarDropdownItem>Item 2</ScalarDropdownItem>\n * </ScalarDropdownMenu>\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\nimport { type Component } from 'vue'\n\ndefineProps<{\n /** The component to render */\n is?: string | Component\n}>()\n\ndefineSlots<{\n /** The menu contents */\n default?(): unknown\n /** Overrides the normal menu list element */\n menu?(): unknown\n}>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <!-- Background container -->\n <component\n :is=\"is ?? 'div'\"\n v-bind=\"\n cx(\n 'relative flex w-56 rounded-xl bg-b-1 dark:bg-b-1.5 shadow-md inset-shadow-border',\n )\n \">\n <!-- Scroll container -->\n <div class=\"custom-scroll min-h-0 flex-1 rounded-[inherit]\">\n <!-- Menu items -->\n <slot name=\"menu\">\n <div class=\"flex flex-col p-0.75\">\n <slot />\n </div>\n </slot>\n </div>\n </component>\n</template>\n"],"mappings":""}
@@ -1,8 +1,7 @@
1
- import ScalarFloatingBackdrop_default from "../ScalarFloating/ScalarFloatingBackdrop.vue.js";
2
1
  import { useBindCx } from "@scalar/use-hooks/useBindCx";
3
- import { createBlock, createElementVNode, createVNode, defineComponent, guardReactiveProps, normalizeProps, openBlock, renderSlot, resolveDynamicComponent, unref, withCtx } from "vue";
2
+ import { createBlock, createElementVNode, defineComponent, guardReactiveProps, normalizeProps, openBlock, renderSlot, resolveDynamicComponent, unref, withCtx } from "vue";
4
3
  //#region src/components/ScalarDropdown/ScalarDropdownMenu.vue?vue&type=script&setup=true&lang.ts
5
- var _hoisted_1 = { class: "custom-scroll min-h-0 flex-1" };
4
+ var _hoisted_1 = { class: "custom-scroll min-h-0 flex-1 rounded-[inherit]" };
6
5
  var _hoisted_2 = { class: "flex flex-col p-0.75" };
7
6
  var ScalarDropdownMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
8
7
  inheritAttrs: false,
@@ -11,8 +10,8 @@ var ScalarDropdownMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__
11
10
  setup(__props) {
12
11
  const { cx } = useBindCx();
13
12
  return (_ctx, _cache) => {
14
- return openBlock(), createBlock(resolveDynamicComponent(__props.is ?? "div"), normalizeProps(guardReactiveProps(unref(cx)("relative flex w-56"))), {
15
- default: withCtx(() => [createElementVNode("div", _hoisted_1, [renderSlot(_ctx.$slots, "menu", {}, () => [createElementVNode("div", _hoisted_2, [renderSlot(_ctx.$slots, "default")])]), renderSlot(_ctx.$slots, "backdrop", {}, () => [createVNode(unref(ScalarFloatingBackdrop_default), { class: "rounded-xl border shadow-md" })])])]),
13
+ return openBlock(), createBlock(resolveDynamicComponent(__props.is ?? "div"), normalizeProps(guardReactiveProps(unref(cx)("relative flex w-56 rounded-xl bg-b-1 dark:bg-b-1.5 shadow-md inset-shadow-border"))), {
14
+ default: withCtx(() => [createElementVNode("div", _hoisted_1, [renderSlot(_ctx.$slots, "menu", {}, () => [createElementVNode("div", _hoisted_2, [renderSlot(_ctx.$slots, "default")])])])]),
16
15
  _: 3
17
16
  }, 16);
18
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarDropdownMenu.vue.script.js","names":[],"sources":["../../../src/components/ScalarDropdown/ScalarDropdownMenu.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar dropdown menu component\n *\n * Provides a scrollable container for dropdown items\n * This is used internally by the ScalarDropdown component\n *\n * If you're looking to create a dropdown menu with a trigger\n * button you probably want the ScalarDropdown component\n *\n * @example\n * <ScalarDropdownMenu>\n * <ScalarDropdownItem>Item 1</ScalarDropdownItem>\n * <ScalarDropdownItem>Item 2</ScalarDropdownItem>\n * </ScalarDropdownMenu>\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\nimport { type Component } from 'vue'\n\nimport { ScalarFloatingBackdrop } from '../ScalarFloating'\n\ndefineProps<{\n /** The component to render */\n is?: string | Component\n}>()\n\ndefineSlots<{\n /** The menu contents */\n default?(): unknown\n /** Overrides the normal menu list element */\n menu?(): unknown\n /** Overrides the backdrop for the dropdown */\n backdrop?(): unknown\n}>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <!-- Background container -->\n <component\n :is=\"is ?? 'div'\"\n v-bind=\"cx('relative flex w-56')\">\n <!-- Scroll container -->\n <div class=\"custom-scroll min-h-0 flex-1\">\n <!-- Menu items -->\n <slot name=\"menu\">\n <div class=\"flex flex-col p-0.75\">\n <slot />\n </div>\n </slot>\n <slot name=\"backdrop\">\n <ScalarFloatingBackdrop class=\"rounded-xl border shadow-md\" />\n </slot>\n </div>\n </component>\n</template>\n"],"mappings":";;;;;;;;;;;EAuCA,MAAM,EAAE,OAAO,UAAU;;uBAIvB,YAeY,wBAdL,QAAA,MAAE,KAAA,GAAA,eAAA,mBACC,MAAA,EAAA,CAAE,CAAA,oBAAA,CAAA,CAAA,GAAA;2BAYJ,CAVN,mBAUM,OAVN,YAUM,CARJ,WAIO,KAAA,QAAA,QAAA,CAAA,SAAA,CAHL,mBAEM,OAFN,YAEM,CADJ,WAAQ,KAAA,QAAA,SAAA,CAAA,CAAA,CAAA,CAAA,GAGZ,WAEO,KAAA,QAAA,YAAA,CAAA,SAAA,CADL,YAA8D,MAAA,8BAAA,GAAA,EAAtC,OAAM,8BAA6B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"ScalarDropdownMenu.vue.script.js","names":[],"sources":["../../../src/components/ScalarDropdown/ScalarDropdownMenu.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar dropdown menu component\n *\n * Provides a scrollable container for dropdown items\n * This is used internally by the ScalarDropdown component\n *\n * If you're looking to create a dropdown menu with a trigger\n * button you probably want the ScalarDropdown component\n *\n * @example\n * <ScalarDropdownMenu>\n * <ScalarDropdownItem>Item 1</ScalarDropdownItem>\n * <ScalarDropdownItem>Item 2</ScalarDropdownItem>\n * </ScalarDropdownMenu>\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\nimport { type Component } from 'vue'\n\ndefineProps<{\n /** The component to render */\n is?: string | Component\n}>()\n\ndefineSlots<{\n /** The menu contents */\n default?(): unknown\n /** Overrides the normal menu list element */\n menu?(): unknown\n}>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <!-- Background container -->\n <component\n :is=\"is ?? 'div'\"\n v-bind=\"\n cx(\n 'relative flex w-56 rounded-xl bg-b-1 dark:bg-b-1.5 shadow-md inset-shadow-border',\n )\n \">\n <!-- Scroll container -->\n <div class=\"custom-scroll min-h-0 flex-1 rounded-[inherit]\">\n <!-- Menu items -->\n <slot name=\"menu\">\n <div class=\"flex flex-col p-0.75\">\n <slot />\n </div>\n </slot>\n </div>\n </component>\n</template>\n"],"mappings":";;;;;;;;;;EAmCA,MAAM,EAAE,OAAO,UAAU;;uBAIvB,YAgBY,wBAfL,QAAA,MAAE,KAAA,GAAA,eAAA,mBACQ,MAAA,EAAA,CAAE,CAAA,kFAAA,CAAA,CAAA,GAAA;2BAaX,CAPN,mBAOM,OAPN,YAOM,CALJ,WAIO,KAAA,QAAA,QAAA,CAAA,SAAA,CAHL,mBAEM,OAFN,YAEM,CADJ,WAAQ,KAAA,QAAA,SAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA"}
@@ -1,20 +1,14 @@
1
1
  /**
2
2
  * Scalar floating backdrop component
3
3
  *
4
- * Provides an absolutely positioned backdrop for the floating element
5
- * This is used internally by a number of the Scalar floating components
6
- * (e.g. Dropdown, Popover, Listbox)
4
+ * Provides an absolutely positioned surface behind a floating element
7
5
  *
8
- * You can use this component directly if you need to customize the backdrop
9
- * for a floating component
6
+ * The backdrop inherits its border radius from its parent, so set the radius
7
+ * on the floating element itself and the backdrop will follow it
10
8
  *
11
- * @example
12
- * <ScalarDropdown>
13
- * <!-- Menu stuff -->
14
- * <template #backdrop>
15
- * <ScalarFloatingBackdrop />
16
- * </template>
17
- * </ScalarDropdown>
9
+ * @deprecated The Scalar floating components now paint their own surface, so
10
+ * style the floating element directly instead, e.g.
11
+ * `rounded-xl bg-b-1 dark:bg-b-1.5 shadow-md inset-shadow-border`
18
12
  */
19
13
  declare const _default: typeof __VLS_export;
20
14
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarFloatingBackdrop.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarFloating/ScalarFloatingBackdrop.vue"],"names":[],"mappings":"AAyCA;;;;;;;;;;;;;;;;;GAiBG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;cA4BJ,CAAC,KAAK,IAAgB,KAAK,GAAG;EAQxC,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"ScalarFloatingBackdrop.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarFloating/ScalarFloatingBackdrop.vue"],"names":[],"mappings":"AAqCA;;;;;;;;;;;GAWG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;cA8BJ,CAAC,KAAK,IAAgB,KAAK,GAAG;EAQxC,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarFloatingBackdrop.vue.js","names":[],"sources":["../../../src/components/ScalarFloating/ScalarFloatingBackdrop.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar floating backdrop component\n *\n * Provides an absolutely positioned backdrop for the floating element\n * This is used internally by a number of the Scalar floating components\n * (e.g. Dropdown, Popover, Listbox)\n *\n * You can use this component directly if you need to customize the backdrop\n * for a floating component\n *\n * @example\n * <ScalarDropdown>\n * <!-- Menu stuff -->\n * <template #backdrop>\n * <ScalarFloatingBackdrop />\n * </template>\n * </ScalarDropdown>\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <div\n v-bind=\"\n cx('absolute inset-0 -z-1 rounded bg-b-1 shadow-lg brightness-lifted')\n \">\n <slot />\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ScalarFloatingBackdrop.vue.js","names":[],"sources":["../../../src/components/ScalarFloating/ScalarFloatingBackdrop.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar floating backdrop component\n *\n * Provides an absolutely positioned surface behind a floating element\n *\n * The backdrop inherits its border radius from its parent, so set the radius\n * on the floating element itself and the backdrop will follow it\n *\n * @deprecated The Scalar floating components now paint their own surface, so\n * style the floating element directly instead, e.g.\n * `rounded-xl bg-b-1 dark:bg-b-1.5 shadow-md inset-shadow-border`\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <div\n v-bind=\"\n cx(\n 'absolute inset-0 -z-1 rounded-[inherit] bg-b-1 dark:bg-b-1.5 shadow-md inset-shadow-border',\n )\n \">\n <slot />\n </div>\n</template>\n"],"mappings":""}
@@ -6,7 +6,7 @@ var ScalarFloatingBackdrop_vue_vue_type_script_setup_true_lang_default = /*@__PU
6
6
  setup(__props) {
7
7
  const { cx } = useBindCx();
8
8
  return (_ctx, _cache) => {
9
- return openBlock(), createElementBlock("div", normalizeProps(guardReactiveProps(unref(cx)("absolute inset-0 -z-1 rounded bg-b-1 shadow-lg brightness-lifted"))), [renderSlot(_ctx.$slots, "default")], 16);
9
+ return openBlock(), createElementBlock("div", normalizeProps(guardReactiveProps(unref(cx)("absolute inset-0 -z-1 rounded-[inherit] bg-b-1 dark:bg-b-1.5 shadow-md inset-shadow-border"))), [renderSlot(_ctx.$slots, "default")], 16);
10
10
  };
11
11
  }
12
12
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarFloatingBackdrop.vue.script.js","names":[],"sources":["../../../src/components/ScalarFloating/ScalarFloatingBackdrop.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar floating backdrop component\n *\n * Provides an absolutely positioned backdrop for the floating element\n * This is used internally by a number of the Scalar floating components\n * (e.g. Dropdown, Popover, Listbox)\n *\n * You can use this component directly if you need to customize the backdrop\n * for a floating component\n *\n * @example\n * <ScalarDropdown>\n * <!-- Menu stuff -->\n * <template #backdrop>\n * <ScalarFloatingBackdrop />\n * </template>\n * </ScalarDropdown>\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <div\n v-bind=\"\n cx('absolute inset-0 -z-1 rounded bg-b-1 shadow-lg brightness-lifted')\n \">\n <slot />\n </div>\n</template>\n"],"mappings":";;;;;;EAyBA,MAAM,EAAE,OAAO,UAAU;;uBAGvB,mBAKM,OAAA,eAAA,mBAJW,MAAA,EAAA,CAAE,CAAA,kEAAA,CAAA,CAAA,GAAA,CAGjB,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,EAAA"}
1
+ {"version":3,"file":"ScalarFloatingBackdrop.vue.script.js","names":[],"sources":["../../../src/components/ScalarFloating/ScalarFloatingBackdrop.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar floating backdrop component\n *\n * Provides an absolutely positioned surface behind a floating element\n *\n * The backdrop inherits its border radius from its parent, so set the radius\n * on the floating element itself and the backdrop will follow it\n *\n * @deprecated The Scalar floating components now paint their own surface, so\n * style the floating element directly instead, e.g.\n * `rounded-xl bg-b-1 dark:bg-b-1.5 shadow-md inset-shadow-border`\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <div\n v-bind=\"\n cx(\n 'absolute inset-0 -z-1 rounded-[inherit] bg-b-1 dark:bg-b-1.5 shadow-md inset-shadow-border',\n )\n \">\n <slot />\n </div>\n</template>\n"],"mappings":";;;;;;EAmBA,MAAM,EAAE,OAAO,UAAU;;uBAGvB,mBAOM,OAAA,eAAA,mBANW,MAAA,EAAA,CAAE,CAAA,4FAAA,CAAA,CAAA,GAAA,CAKjB,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,EAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarListbox.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarListbox/ScalarListbox.vue"],"names":[],"mappings":"AA4HA,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAA;AAE1B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAGrC;;;;;;;;;;GAUG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;aAYL,MAAM,EAAE;SACZ,MAAM;YACH,MAAM;;eAZL,KAAK,GAAG,SAAS;iBACf,MAAM,GAAG,SAAS;;aASpB,MAAM,EAAE;SACZ,MAAM;YACH,MAAM;;cAPN,IAAI;iBACD,MAAM,EAAE,GAAG,SAAS;;;;aAItB,MAAM,EAAE;SACZ,MAAM;YACH,MAAM;;eAZL,KAAK,GAAG,SAAS;iBACf,MAAM,GAAG,SAAS;;aASpB,MAAM,EAAE;SACZ,MAAM;YACH,MAAM;;cAPN,IAAI;iBACD,MAAM,EAAE,GAAG,SAAS;;;;IAmBjC,4CAA4C;mBAC7B;QACb,yCAAyC;QACzC,IAAI,EAAE,OAAO,CAAA;KACd,GAAG,OAAO;EA4LT,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"ScalarListbox.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarListbox/ScalarListbox.vue"],"names":[],"mappings":"AAuHA,OAAO,EAAkB,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAE9E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAGrC;;;;;;;;;;GAUG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;aAYL,MAAM,EAAE;SACZ,MAAM;YACH,MAAM;;eAZL,KAAK,GAAG,SAAS;iBACf,MAAM,GAAG,SAAS;;aASpB,MAAM,EAAE;SACZ,MAAM;YACH,MAAM;;cAPN,IAAI;iBACD,MAAM,EAAE,GAAG,SAAS;;;;aAItB,MAAM,EAAE;SACZ,MAAM;YACH,MAAM;;eAZL,KAAK,GAAG,SAAS;iBACf,MAAM,GAAG,SAAS;;aASpB,MAAM,EAAE;SACZ,MAAM;YACH,MAAM;;cAPN,IAAI;iBACD,MAAM,EAAE,GAAG,SAAS;;;;IAmBjC,4CAA4C;mBAC7B;QACb,yCAAyC;QACzC,IAAI,EAAE,OAAO,CAAA;KACd,GAAG,OAAO;EAoLT,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarListbox.vue.js","names":[],"sources":["../../../src/components/ScalarListbox/ScalarListbox.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Listbox component\n *\n * A dropdown select component built on HeadlessUI Listbox.\n * Supports single and multiple selection modes.\n *\n * @example\n * <ScalarListbox v-model=\"selected\" :options=\"options\">\n * <ScalarButton>{{ selected?.label ?? 'Select' }}</ScalarButton>\n * </ScalarListbox>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n Listbox,\n ListboxButton,\n ListboxLabel,\n ListboxOptions,\n} from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\nimport {\n ScalarFloating,\n ScalarFloatingBackdrop,\n type ScalarFloatingOptions,\n} from '../ScalarFloating'\nimport ScalarListboxOption from './ScalarListboxItem.vue'\nimport type { Option } from './types'\n\ntype SingleSelectListboxProps = {\n multiple?: false | undefined\n modelValue?: Option | undefined\n}\n\ntype MultipleSelectListboxProps = {\n multiple: true\n modelValue?: Option[] | undefined\n}\n\ndefineProps<\n {\n options: Option[]\n id?: string\n label?: string\n } & (SingleSelectListboxProps | MultipleSelectListboxProps) &\n ScalarFloatingOptions\n>()\n\ndefineEmits<{\n (e: 'update:modelValue', v: Option): void\n}>()\n\ndefineSlots<{\n /** The reference element for the listbox */\n default(props: {\n /** Whether or not the listbox is open */\n open: boolean\n }): unknown\n}>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <Listbox\n v-slot=\"{ open }\"\n :modelValue=\"modelValue\"\n :multiple=\"multiple\"\n @update:modelValue=\"(v) => $emit('update:modelValue', v)\">\n <ListboxLabel\n v-if=\"label\"\n class=\"sr-only\">\n {{ label }}\n </ListboxLabel>\n <ScalarFloating\n v-bind=\"$props\"\n :placement=\"placement ?? 'bottom-start'\">\n <ListboxButton\n :id=\"id\"\n as=\"template\">\n <slot :open=\"open\" />\n </ListboxButton>\n <template #floating=\"{ width }\">\n <!-- Background container -->\n <div\n v-if=\"open\"\n :style=\"{ width }\"\n v-bind=\"\n cx(\n 'relative flex max-h-[inherit] w-40 max-w-[inherit] rounded text-sm',\n )\n \">\n <!-- Scroll container -->\n <div class=\"custom-scroll min-h-0 flex-1\">\n <!-- Options list -->\n <ListboxOptions\n class=\"flex flex-col gap-0.75 p-0.75 -outline-offset-1\">\n <ScalarListboxOption\n v-for=\"option in options\"\n :key=\"option.id\"\n :multiselect=\"multiple\"\n :option=\"option\" />\n </ListboxOptions>\n </div>\n <ScalarFloatingBackdrop />\n </div>\n </template>\n </ScalarFloating>\n </Listbox>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ScalarListbox.vue.js","names":[],"sources":["../../../src/components/ScalarListbox/ScalarListbox.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Listbox component\n *\n * A dropdown select component built on HeadlessUI Listbox.\n * Supports single and multiple selection modes.\n *\n * @example\n * <ScalarListbox v-model=\"selected\" :options=\"options\">\n * <ScalarButton>{{ selected?.label ?? 'Select' }}</ScalarButton>\n * </ScalarListbox>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n Listbox,\n ListboxButton,\n ListboxLabel,\n ListboxOptions,\n} from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\nimport { ScalarFloating, type ScalarFloatingOptions } from '../ScalarFloating'\nimport ScalarListboxOption from './ScalarListboxItem.vue'\nimport type { Option } from './types'\n\ntype SingleSelectListboxProps = {\n multiple?: false | undefined\n modelValue?: Option | undefined\n}\n\ntype MultipleSelectListboxProps = {\n multiple: true\n modelValue?: Option[] | undefined\n}\n\ndefineProps<\n {\n options: Option[]\n id?: string\n label?: string\n } & (SingleSelectListboxProps | MultipleSelectListboxProps) &\n ScalarFloatingOptions\n>()\n\ndefineEmits<{\n (e: 'update:modelValue', v: Option): void\n}>()\n\ndefineSlots<{\n /** The reference element for the listbox */\n default(props: {\n /** Whether or not the listbox is open */\n open: boolean\n }): unknown\n}>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <Listbox\n v-slot=\"{ open }\"\n :modelValue=\"modelValue\"\n :multiple=\"multiple\"\n @update:modelValue=\"(v) => $emit('update:modelValue', v)\">\n <ListboxLabel\n v-if=\"label\"\n class=\"sr-only\">\n {{ label }}\n </ListboxLabel>\n <ScalarFloating\n v-bind=\"$props\"\n :placement=\"placement ?? 'bottom-start'\">\n <ListboxButton\n :id=\"id\"\n as=\"template\">\n <slot :open=\"open\" />\n </ListboxButton>\n <template #floating=\"{ width }\">\n <!-- Background container -->\n <div\n v-if=\"open\"\n :style=\"{ width }\"\n v-bind=\"\n cx(\n 'relative flex max-h-[inherit] w-40 max-w-[inherit] rounded-xl bg-b-1 dark:bg-b-1.5 text-sm shadow-md inset-shadow-border',\n )\n \">\n <!-- Scroll container -->\n <div class=\"custom-scroll min-h-0 flex-1 rounded-[inherit]\">\n <!-- Options list -->\n <ListboxOptions\n class=\"flex flex-col gap-0.75 p-0.75 -outline-offset-1\">\n <ScalarListboxOption\n v-for=\"option in options\"\n :key=\"option.id\"\n :multiselect=\"multiple\"\n :option=\"option\" />\n </ListboxOptions>\n </div>\n </div>\n </template>\n </ScalarFloating>\n </Listbox>\n</template>\n"],"mappings":""}
@@ -1,11 +1,10 @@
1
1
  import ScalarFloating_default from "../ScalarFloating/ScalarFloating.vue.js";
2
- import ScalarFloatingBackdrop_default from "../ScalarFloating/ScalarFloatingBackdrop.vue.js";
3
2
  import ScalarListboxItem_default from "./ScalarListboxItem.vue.js";
4
3
  import { useBindCx } from "@scalar/use-hooks/useBindCx";
5
4
  import { Fragment, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeProps, openBlock, renderList, renderSlot, toDisplayString, unref, withCtx } from "vue";
6
5
  import { Listbox, ListboxButton, ListboxLabel, ListboxOptions } from "@headlessui/vue";
7
6
  //#region src/components/ScalarListbox/ScalarListbox.vue?vue&type=script&setup=true&lang.ts
8
- var _hoisted_1 = { class: "custom-scroll min-h-0 flex-1" };
7
+ var _hoisted_1 = { class: "custom-scroll min-h-0 flex-1 rounded-[inherit]" };
9
8
  var ScalarListbox_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
10
9
  inheritAttrs: false,
11
10
  __name: "ScalarListbox",
@@ -45,7 +44,7 @@ var ScalarListbox_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
45
44
  floating: withCtx(({ width }) => [open ? (openBlock(), createElementBlock("div", mergeProps({
46
45
  key: 0,
47
46
  style: { width }
48
- }, unref(cx)("relative flex max-h-[inherit] w-40 max-w-[inherit] rounded text-sm")), [createElementVNode("div", _hoisted_1, [createVNode(unref(ListboxOptions), { class: "flex flex-col gap-0.75 p-0.75 -outline-offset-1" }, {
47
+ }, unref(cx)("relative flex max-h-[inherit] w-40 max-w-[inherit] rounded-xl bg-b-1 dark:bg-b-1.5 text-sm shadow-md inset-shadow-border")), [createElementVNode("div", _hoisted_1, [createVNode(unref(ListboxOptions), { class: "flex flex-col gap-0.75 p-0.75 -outline-offset-1" }, {
49
48
  default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.options, (option) => {
50
49
  return openBlock(), createBlock(ScalarListboxItem_default, {
51
50
  key: option.id,
@@ -54,7 +53,7 @@ var ScalarListbox_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
54
53
  }, null, 8, ["multiselect", "option"]);
55
54
  }), 128))]),
56
55
  _: 1
57
- })]), createVNode(unref(ScalarFloatingBackdrop_default))], 16)) : createCommentVNode("", true)]),
56
+ })])], 16)) : createCommentVNode("", true)]),
58
57
  default: withCtx(() => [createVNode(unref(ListboxButton), {
59
58
  id: __props.id,
60
59
  as: "template"
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarListbox.vue.script.js","names":["$emit","$props"],"sources":["../../../src/components/ScalarListbox/ScalarListbox.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Listbox component\n *\n * A dropdown select component built on HeadlessUI Listbox.\n * Supports single and multiple selection modes.\n *\n * @example\n * <ScalarListbox v-model=\"selected\" :options=\"options\">\n * <ScalarButton>{{ selected?.label ?? 'Select' }}</ScalarButton>\n * </ScalarListbox>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n Listbox,\n ListboxButton,\n ListboxLabel,\n ListboxOptions,\n} from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\nimport {\n ScalarFloating,\n ScalarFloatingBackdrop,\n type ScalarFloatingOptions,\n} from '../ScalarFloating'\nimport ScalarListboxOption from './ScalarListboxItem.vue'\nimport type { Option } from './types'\n\ntype SingleSelectListboxProps = {\n multiple?: false | undefined\n modelValue?: Option | undefined\n}\n\ntype MultipleSelectListboxProps = {\n multiple: true\n modelValue?: Option[] | undefined\n}\n\ndefineProps<\n {\n options: Option[]\n id?: string\n label?: string\n } & (SingleSelectListboxProps | MultipleSelectListboxProps) &\n ScalarFloatingOptions\n>()\n\ndefineEmits<{\n (e: 'update:modelValue', v: Option): void\n}>()\n\ndefineSlots<{\n /** The reference element for the listbox */\n default(props: {\n /** Whether or not the listbox is open */\n open: boolean\n }): unknown\n}>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <Listbox\n v-slot=\"{ open }\"\n :modelValue=\"modelValue\"\n :multiple=\"multiple\"\n @update:modelValue=\"(v) => $emit('update:modelValue', v)\">\n <ListboxLabel\n v-if=\"label\"\n class=\"sr-only\">\n {{ label }}\n </ListboxLabel>\n <ScalarFloating\n v-bind=\"$props\"\n :placement=\"placement ?? 'bottom-start'\">\n <ListboxButton\n :id=\"id\"\n as=\"template\">\n <slot :open=\"open\" />\n </ListboxButton>\n <template #floating=\"{ width }\">\n <!-- Background container -->\n <div\n v-if=\"open\"\n :style=\"{ width }\"\n v-bind=\"\n cx(\n 'relative flex max-h-[inherit] w-40 max-w-[inherit] rounded text-sm',\n )\n \">\n <!-- Scroll container -->\n <div class=\"custom-scroll min-h-0 flex-1\">\n <!-- Options list -->\n <ListboxOptions\n class=\"flex flex-col gap-0.75 p-0.75 -outline-offset-1\">\n <ScalarListboxOption\n v-for=\"option in options\"\n :key=\"option.id\"\n :multiselect=\"multiple\"\n :option=\"option\" />\n </ListboxOptions>\n </div>\n <ScalarFloatingBackdrop />\n </div>\n </template>\n </ScalarFloating>\n </Listbox>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgEA,MAAM,EAAE,OAAO,UAAU;;uBAGvB,YA4CU,MAAA,OAAA,GAAA;IA1CP,YAAY,QAAA;IACZ,UAAU,QAAA;IACV,uBAAiB,OAAA,OAAA,OAAA,MAAG,MAAMA,KAAAA,MAAK,qBAAsB,CAAC;;sBAKxC,EARL,WAAI,CAKN,QAAA,SAAA,UAAA,GADR,YAIe,MAAA,YAAA,GAAA;;KAFb,OAAM;;4BACK,CAAA,gBAAA,gBAAR,QAAA,KAAK,GAAA,CAAA,CAAA,CAAA;;wCAEV,YAiCiB,MAAA,sBAAA,GAjCjB,WACUC,KAgCO,QAhCD,EACb,WAAW,QAAA,aAAS,eAAA,CAAA,GAAA;KAMV,UAAQ,SAuBX,EAvBe,YAAK,CAGlB,QAAA,UAAA,GADR,mBAqBM,OArBN,WAqBM;;MAnBH,OAAK,EAAI,MAAK;QACM,MAAA,EAAA,CAAE,CAAA,oEAAA,CAAA,GAAA,CAMvB,mBAUM,OAVN,YAUM,CARJ,YAOiB,MAAA,cAAA,GAAA,EANf,OAAM,kDAAiD,GAAA;6BAE5B,EAAA,UAAA,IAAA,GAD3B,mBAIqB,UAAA,MAAA,WAHF,QAAA,UAAV,WAAM;2BADf,YAIqB,2BAAA;QAFlB,KAAK,OAAO;QACZ,aAAa,QAAA;QACL;;;;WAGf,YAA0B,MAAA,8BAAA,CAAA,CAAA,GAAA,EAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA;4BAvBd,CAJhB,YAIgB,MAAA,aAAA,GAAA;MAHb,IAAI,QAAA;MACL,IAAG;;6BACkB,CAArB,WAAqB,KAAA,QAAA,WAAA,EAAR,KAAI,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"ScalarListbox.vue.script.js","names":["$emit","$props"],"sources":["../../../src/components/ScalarListbox/ScalarListbox.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Listbox component\n *\n * A dropdown select component built on HeadlessUI Listbox.\n * Supports single and multiple selection modes.\n *\n * @example\n * <ScalarListbox v-model=\"selected\" :options=\"options\">\n * <ScalarButton>{{ selected?.label ?? 'Select' }}</ScalarButton>\n * </ScalarListbox>\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n Listbox,\n ListboxButton,\n ListboxLabel,\n ListboxOptions,\n} from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\nimport { ScalarFloating, type ScalarFloatingOptions } from '../ScalarFloating'\nimport ScalarListboxOption from './ScalarListboxItem.vue'\nimport type { Option } from './types'\n\ntype SingleSelectListboxProps = {\n multiple?: false | undefined\n modelValue?: Option | undefined\n}\n\ntype MultipleSelectListboxProps = {\n multiple: true\n modelValue?: Option[] | undefined\n}\n\ndefineProps<\n {\n options: Option[]\n id?: string\n label?: string\n } & (SingleSelectListboxProps | MultipleSelectListboxProps) &\n ScalarFloatingOptions\n>()\n\ndefineEmits<{\n (e: 'update:modelValue', v: Option): void\n}>()\n\ndefineSlots<{\n /** The reference element for the listbox */\n default(props: {\n /** Whether or not the listbox is open */\n open: boolean\n }): unknown\n}>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <Listbox\n v-slot=\"{ open }\"\n :modelValue=\"modelValue\"\n :multiple=\"multiple\"\n @update:modelValue=\"(v) => $emit('update:modelValue', v)\">\n <ListboxLabel\n v-if=\"label\"\n class=\"sr-only\">\n {{ label }}\n </ListboxLabel>\n <ScalarFloating\n v-bind=\"$props\"\n :placement=\"placement ?? 'bottom-start'\">\n <ListboxButton\n :id=\"id\"\n as=\"template\">\n <slot :open=\"open\" />\n </ListboxButton>\n <template #floating=\"{ width }\">\n <!-- Background container -->\n <div\n v-if=\"open\"\n :style=\"{ width }\"\n v-bind=\"\n cx(\n 'relative flex max-h-[inherit] w-40 max-w-[inherit] rounded-xl bg-b-1 dark:bg-b-1.5 text-sm shadow-md inset-shadow-border',\n )\n \">\n <!-- Scroll container -->\n <div class=\"custom-scroll min-h-0 flex-1 rounded-[inherit]\">\n <!-- Options list -->\n <ListboxOptions\n class=\"flex flex-col gap-0.75 p-0.75 -outline-offset-1\">\n <ScalarListboxOption\n v-for=\"option in options\"\n :key=\"option.id\"\n :multiselect=\"multiple\"\n :option=\"option\" />\n </ListboxOptions>\n </div>\n </div>\n </template>\n </ScalarFloating>\n </Listbox>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4DA,MAAM,EAAE,OAAO,UAAU;;uBAGvB,YA2CU,MAAA,OAAA,GAAA;IAzCP,YAAY,QAAA;IACZ,UAAU,QAAA;IACV,uBAAiB,OAAA,OAAA,OAAA,MAAG,MAAMA,KAAAA,MAAK,qBAAsB,CAAC;;sBAKxC,EARL,WAAI,CAKN,QAAA,SAAA,UAAA,GADR,YAIe,MAAA,YAAA,GAAA;;KAFb,OAAM;;4BACK,CAAA,gBAAA,gBAAR,QAAA,KAAK,GAAA,CAAA,CAAA,CAAA;;wCAEV,YAgCiB,MAAA,sBAAA,GAhCjB,WACUC,KA+BO,QA/BD,EACb,WAAW,QAAA,aAAS,eAAA,CAAA,GAAA;KAMV,UAAQ,SAsBX,EAtBe,YAAK,CAGlB,QAAA,UAAA,GADR,mBAoBM,OApBN,WAoBM;;MAlBH,OAAK,EAAI,MAAK;QACM,MAAA,EAAA,CAAE,CAAA,0HAAA,CAAA,GAAA,CAMvB,mBAUM,OAVN,YAUM,CARJ,YAOiB,MAAA,cAAA,GAAA,EANf,OAAM,kDAAiD,GAAA;6BAE5B,EAAA,UAAA,IAAA,GAD3B,mBAIqB,UAAA,MAAA,WAHF,QAAA,UAAV,WAAM;2BADf,YAIqB,2BAAA;QAFlB,KAAK,OAAO;QACZ,aAAa,QAAA;QACL;;;;;4BApBH,CAJhB,YAIgB,MAAA,aAAA,GAAA;MAHb,IAAI,QAAA;MACL,IAAG;;6BACkB,CAArB,WAAqB,KAAA,QAAA,WAAA,EAAR,KAAI,CAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarListboxItem.vue.js","names":[],"sources":["../../../src/components/ScalarListbox/ScalarListboxItem.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Listbox Item component\n *\n * A single option within a ScalarListbox dropdown.\n * Handles active, selected, and disabled states.\n *\n * @example\n * <ScalarListboxItem :option=\"{ id: '1', label: 'Option 1' }\" />\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { ListboxOption } from '@headlessui/vue'\nimport { cva, cx } from '@scalar/use-hooks/useBindCx'\n\nimport ScalarListboxCheckbox from './ScalarListboxCheckbox.vue'\nimport type { Option } from './types'\n\ndefineProps<{\n option: Option\n multiselect?: boolean\n}>()\n\nconst variants = cva({\n base: [\n // Layout\n 'group/item',\n 'flex min-w-0 items-center gap-1.5 rounded px-2 py-1.5 text-left',\n // Text / background style\n 'truncate bg-transparent text-c-1',\n // Interaction\n 'cursor-pointer hover:bg-b-2',\n ],\n variants: {\n selected: { true: 'text-c-1' },\n active: { true: 'bg-b-2' },\n disabled: { true: 'pointer-events-none opacity-50' },\n },\n})\n</script>\n<template>\n <ListboxOption\n v-slot=\"{ active, selected }\"\n as=\"template\"\n :disabled=\"option.disabled\"\n :value=\"option\">\n <li :class=\"cx(variants({ active, selected, disabled: option.disabled }))\">\n <ScalarListboxCheckbox\n :multiselect\n :selected />\n <span\n class=\"inline-block min-w-0 flex-1 truncate\"\n :class=\"option.color ? option.color : 'text-c-1'\">\n {{ option.label }}\n </span>\n </li>\n </ListboxOption>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ScalarListboxItem.vue.js","names":[],"sources":["../../../src/components/ScalarListbox/ScalarListboxItem.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Listbox Item component\n *\n * A single option within a ScalarListbox dropdown.\n * Handles active, selected, and disabled states.\n *\n * @example\n * <ScalarListboxItem :option=\"{ id: '1', label: 'Option 1' }\" />\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { ListboxOption } from '@headlessui/vue'\nimport { cva, cx } from '@scalar/use-hooks/useBindCx'\n\nimport ScalarListboxCheckbox from './ScalarListboxCheckbox.vue'\nimport type { Option } from './types'\n\ndefineProps<{\n option: Option\n multiselect?: boolean\n}>()\n\nconst variants = cva({\n base: [\n // Layout\n 'group/item',\n 'flex min-w-0 items-center gap-1.5 rounded-md px-2 py-1.5 text-left',\n // Text / background style\n 'truncate bg-transparent text-c-1',\n // Interaction\n 'cursor-pointer hover:bg-b-2',\n ],\n variants: {\n selected: { true: 'text-c-1' },\n active: { true: 'bg-b-2' },\n disabled: { true: 'pointer-events-none opacity-50' },\n },\n})\n</script>\n<template>\n <ListboxOption\n v-slot=\"{ active, selected }\"\n as=\"template\"\n :disabled=\"option.disabled\"\n :value=\"option\">\n <li :class=\"cx(variants({ active, selected, disabled: option.disabled }))\">\n <ScalarListboxCheckbox\n :multiselect\n :selected />\n <span\n class=\"inline-block min-w-0 flex-1 truncate\"\n :class=\"option.color ? option.color : 'text-c-1'\">\n {{ option.label }}\n </span>\n </li>\n </ListboxOption>\n</template>\n"],"mappings":""}
@@ -12,7 +12,7 @@ var ScalarListboxItem_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
12
12
  const variants = cva({
13
13
  base: [
14
14
  "group/item",
15
- "flex min-w-0 items-center gap-1.5 rounded px-2 py-1.5 text-left",
15
+ "flex min-w-0 items-center gap-1.5 rounded-md px-2 py-1.5 text-left",
16
16
  "truncate bg-transparent text-c-1",
17
17
  "cursor-pointer hover:bg-b-2"
18
18
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarListboxItem.vue.script.js","names":[],"sources":["../../../src/components/ScalarListbox/ScalarListboxItem.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Listbox Item component\n *\n * A single option within a ScalarListbox dropdown.\n * Handles active, selected, and disabled states.\n *\n * @example\n * <ScalarListboxItem :option=\"{ id: '1', label: 'Option 1' }\" />\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { ListboxOption } from '@headlessui/vue'\nimport { cva, cx } from '@scalar/use-hooks/useBindCx'\n\nimport ScalarListboxCheckbox from './ScalarListboxCheckbox.vue'\nimport type { Option } from './types'\n\ndefineProps<{\n option: Option\n multiselect?: boolean\n}>()\n\nconst variants = cva({\n base: [\n // Layout\n 'group/item',\n 'flex min-w-0 items-center gap-1.5 rounded px-2 py-1.5 text-left',\n // Text / background style\n 'truncate bg-transparent text-c-1',\n // Interaction\n 'cursor-pointer hover:bg-b-2',\n ],\n variants: {\n selected: { true: 'text-c-1' },\n active: { true: 'bg-b-2' },\n disabled: { true: 'pointer-events-none opacity-50' },\n },\n})\n</script>\n<template>\n <ListboxOption\n v-slot=\"{ active, selected }\"\n as=\"template\"\n :disabled=\"option.disabled\"\n :value=\"option\">\n <li :class=\"cx(variants({ active, selected, disabled: option.disabled }))\">\n <ScalarListboxCheckbox\n :multiselect\n :selected />\n <span\n class=\"inline-block min-w-0 flex-1 truncate\"\n :class=\"option.color ? option.color : 'text-c-1'\">\n {{ option.label }}\n </span>\n </li>\n </ListboxOption>\n</template>\n"],"mappings":";;;;;;;;;;;EAyBA,MAAM,WAAW,IAAI;GACnB,MAAM;IAEJ;IACA;IAEA;IAEA;GACF;GACA,UAAU;IACR,UAAU,EAAE,MAAM,WAAW;IAC7B,QAAQ,EAAE,MAAM,SAAS;IACzB,UAAU,EAAE,MAAM,iCAAiC;GACrD;EACF,CAAC;;uBAGC,YAegB,MAAA,aAAA,GAAA;IAbd,IAAG;IACF,UAAU,QAAA,OAAO;IACjB,OAAO,QAAA;;sBAUH,EAbK,QAAQ,eAAQ,CAI1B,mBASK,MAAA,EATA,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,MAAA,QAAA,CAAQ,CAAA;KAAG;KAAQ;KAAQ,UAAY,QAAA,OAAO;IAAQ,CAAA,CAAA,CAAA,EAAA,GAAA,CACnE,YAEc,+BAAA;KADX,aAAA,QAAA;KACA;8CACH,mBAIO,QAAA,EAHL,OAAK,eAAA,CAAC,wCACE,QAAA,OAAO,QAAQ,QAAA,OAAO,QAAK,UAAA,CAAA,EAAA,GAAA,gBAChC,QAAA,OAAO,KAAK,GAAA,CAAA,CAAA,GAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"ScalarListboxItem.vue.script.js","names":[],"sources":["../../../src/components/ScalarListbox/ScalarListboxItem.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Listbox Item component\n *\n * A single option within a ScalarListbox dropdown.\n * Handles active, selected, and disabled states.\n *\n * @example\n * <ScalarListboxItem :option=\"{ id: '1', label: 'Option 1' }\" />\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { ListboxOption } from '@headlessui/vue'\nimport { cva, cx } from '@scalar/use-hooks/useBindCx'\n\nimport ScalarListboxCheckbox from './ScalarListboxCheckbox.vue'\nimport type { Option } from './types'\n\ndefineProps<{\n option: Option\n multiselect?: boolean\n}>()\n\nconst variants = cva({\n base: [\n // Layout\n 'group/item',\n 'flex min-w-0 items-center gap-1.5 rounded-md px-2 py-1.5 text-left',\n // Text / background style\n 'truncate bg-transparent text-c-1',\n // Interaction\n 'cursor-pointer hover:bg-b-2',\n ],\n variants: {\n selected: { true: 'text-c-1' },\n active: { true: 'bg-b-2' },\n disabled: { true: 'pointer-events-none opacity-50' },\n },\n})\n</script>\n<template>\n <ListboxOption\n v-slot=\"{ active, selected }\"\n as=\"template\"\n :disabled=\"option.disabled\"\n :value=\"option\">\n <li :class=\"cx(variants({ active, selected, disabled: option.disabled }))\">\n <ScalarListboxCheckbox\n :multiselect\n :selected />\n <span\n class=\"inline-block min-w-0 flex-1 truncate\"\n :class=\"option.color ? option.color : 'text-c-1'\">\n {{ option.label }}\n </span>\n </li>\n </ListboxOption>\n</template>\n"],"mappings":";;;;;;;;;;;EAyBA,MAAM,WAAW,IAAI;GACnB,MAAM;IAEJ;IACA;IAEA;IAEA;GACF;GACA,UAAU;IACR,UAAU,EAAE,MAAM,WAAW;IAC7B,QAAQ,EAAE,MAAM,SAAS;IACzB,UAAU,EAAE,MAAM,iCAAiC;GACrD;EACF,CAAC;;uBAGC,YAegB,MAAA,aAAA,GAAA;IAbd,IAAG;IACF,UAAU,QAAA,OAAO;IACjB,OAAO,QAAA;;sBAUH,EAbK,QAAQ,eAAQ,CAI1B,mBASK,MAAA,EATA,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,MAAA,QAAA,CAAQ,CAAA;KAAG;KAAQ;KAAQ,UAAY,QAAA,OAAO;IAAQ,CAAA,CAAA,CAAA,EAAA,GAAA,CACnE,YAEc,+BAAA;KADX,aAAA,QAAA;KACA;8CACH,mBAIO,QAAA,EAHL,OAAK,eAAA,CAAC,wCACE,QAAA,OAAO,QAAQ,QAAA,OAAO,QAAK,UAAA,CAAA,EAAA,GAAA,gBAChC,QAAA,OAAO,KAAK,GAAA,CAAA,CAAA,GAAA,CAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarPopover.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarPopover/ScalarPopover.vue"],"names":[],"mappings":"AAwEA,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAGpC;;;;;;;;;;;GAWG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;IAEd,0DAA0D;YAClD,OAAO;;IADf,0DAA0D;YAClD,OAAO;iIAuIf,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"ScalarPopover.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarPopover/ScalarPopover.vue"],"names":[],"mappings":"AAmEA,OAAO,EAAkB,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAC9E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAGpC;;;;;;;;;;;GAWG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;IAEd,0DAA0D;YAClD,OAAO;;IADf,0DAA0D;YAClD,OAAO;iIAmIf,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarPopover.vue.js","names":[],"sources":["../../../src/components/ScalarPopover/ScalarPopover.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Popover component\n *\n * A floating panel that appears when a trigger element is clicked.\n * Built on HeadlessUI Popover with Floating UI positioning.\n *\n * @example\n * <ScalarPopover>\n * <button>Open</button>\n * <template #popover=\"{ close }\">Popover content</template>\n * </ScalarPopover>\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\nimport {\n ScalarFloating,\n ScalarFloatingBackdrop,\n type ScalarFloatingOptions,\n} from '../ScalarFloating'\nimport type { Slots } from './types'\n\ndefineProps<\n {\n /** Automatically focus the popover panel when it opens */\n focus?: boolean\n } & ScalarFloatingOptions\n>()\n\ndefineSlots<Slots>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <Popover\n v-slot=\"{ open }\"\n as=\"template\">\n <ScalarFloating v-bind=\"$props\">\n <PopoverButton as=\"template\">\n <slot :open=\"open\" />\n </PopoverButton>\n <template #floating=\"{ width, height }\">\n <PopoverPanel\n v-slot=\"{ close }\"\n :focus=\"focus\"\n :style=\"{ width, height }\"\n v-bind=\"cx('relative flex flex-col p-0.75')\">\n <slot\n :close=\"() => close()\"\n name=\"popover\"\n :open=\"open\" />\n <slot\n name=\"backdrop\"\n :open=\"open\">\n <ScalarFloatingBackdrop />\n </slot>\n </PopoverPanel>\n </template>\n </ScalarFloating>\n </Popover>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ScalarPopover.vue.js","names":[],"sources":["../../../src/components/ScalarPopover/ScalarPopover.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Popover component\n *\n * A floating panel that appears when a trigger element is clicked.\n * Built on HeadlessUI Popover with Floating UI positioning.\n *\n * @example\n * <ScalarPopover>\n * <button>Open</button>\n * <template #popover=\"{ close }\">Popover content</template>\n * </ScalarPopover>\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\nimport { ScalarFloating, type ScalarFloatingOptions } from '../ScalarFloating'\nimport type { Slots } from './types'\n\ndefineProps<\n {\n /** Automatically focus the popover panel when it opens */\n focus?: boolean\n } & ScalarFloatingOptions\n>()\n\ndefineSlots<Slots>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <Popover\n v-slot=\"{ open }\"\n as=\"template\">\n <ScalarFloating v-bind=\"$props\">\n <PopoverButton as=\"template\">\n <slot :open=\"open\" />\n </PopoverButton>\n <template #floating=\"{ width, height }\">\n <PopoverPanel\n v-slot=\"{ close }\"\n :focus=\"focus\"\n :style=\"{ width, height }\"\n v-bind=\"\n cx(\n 'relative flex flex-col rounded-xl bg-b-1 dark:bg-b-1.5 p-0.75 shadow-md inset-shadow-border',\n )\n \">\n <slot\n :close=\"() => close()\"\n name=\"popover\"\n :open=\"open\" />\n </PopoverPanel>\n </template>\n </ScalarFloating>\n </Popover>\n</template>\n"],"mappings":""}
@@ -1,5 +1,4 @@
1
1
  import ScalarFloating_default from "../ScalarFloating/ScalarFloating.vue.js";
2
- import ScalarFloatingBackdrop_default from "../ScalarFloating/ScalarFloatingBackdrop.vue.js";
3
2
  import { useBindCx } from "@scalar/use-hooks/useBindCx";
4
3
  import { createBlock, createVNode, defineComponent, guardReactiveProps, mergeProps, normalizeProps, openBlock, renderSlot, unref, withCtx } from "vue";
5
4
  import { Popover, PopoverButton, PopoverPanel } from "@headlessui/vue";
@@ -30,11 +29,11 @@ var ScalarPopover_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
30
29
  width,
31
30
  height
32
31
  }
33
- }, unref(cx)("relative flex flex-col p-0.75")), {
32
+ }, unref(cx)("relative flex flex-col rounded-xl bg-b-1 dark:bg-b-1.5 p-0.75 shadow-md inset-shadow-border")), {
34
33
  default: withCtx(({ close }) => [renderSlot(_ctx.$slots, "popover", {
35
34
  close: () => close(),
36
35
  open
37
- }), renderSlot(_ctx.$slots, "backdrop", { open }, () => [createVNode(unref(ScalarFloatingBackdrop_default))])]),
36
+ })]),
38
37
  _: 2
39
38
  }, 1040, ["focus", "style"])]),
40
39
  default: withCtx(() => [createVNode(unref(PopoverButton), { as: "template" }, {
@@ -1 +1 @@
1
- {"version":3,"file":"ScalarPopover.vue.script.js","names":["$props"],"sources":["../../../src/components/ScalarPopover/ScalarPopover.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Popover component\n *\n * A floating panel that appears when a trigger element is clicked.\n * Built on HeadlessUI Popover with Floating UI positioning.\n *\n * @example\n * <ScalarPopover>\n * <button>Open</button>\n * <template #popover=\"{ close }\">Popover content</template>\n * </ScalarPopover>\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\nimport {\n ScalarFloating,\n ScalarFloatingBackdrop,\n type ScalarFloatingOptions,\n} from '../ScalarFloating'\nimport type { Slots } from './types'\n\ndefineProps<\n {\n /** Automatically focus the popover panel when it opens */\n focus?: boolean\n } & ScalarFloatingOptions\n>()\n\ndefineSlots<Slots>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <Popover\n v-slot=\"{ open }\"\n as=\"template\">\n <ScalarFloating v-bind=\"$props\">\n <PopoverButton as=\"template\">\n <slot :open=\"open\" />\n </PopoverButton>\n <template #floating=\"{ width, height }\">\n <PopoverPanel\n v-slot=\"{ close }\"\n :focus=\"focus\"\n :style=\"{ width, height }\"\n v-bind=\"cx('relative flex flex-col p-0.75')\">\n <slot\n :close=\"() => close()\"\n name=\"popover\"\n :open=\"open\" />\n <slot\n name=\"backdrop\"\n :open=\"open\">\n <ScalarFloatingBackdrop />\n </slot>\n </PopoverPanel>\n </template>\n </ScalarFloating>\n </Popover>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAoCA,MAAM,EAAE,OAAO,UAAU;;uBAGvB,YAyBU,MAAA,OAAA,GAAA,EAvBR,IAAG,WAAU,GAAA;sBAsBI,EAvBP,WAAI,CAEd,YAqBiB,MAAA,sBAAA,GAAA,eAAA,mBArBOA,KAAAA,MAAM,CAAA,GAAA;KAIjB,UAAQ,SAeF,EAfM,OAAO,aAAM,CAClC,YAce,MAAA,YAAA,GAdf,WAce;MAZZ,OAAO,QAAA;MACP,OAAK;OAAI;OAAO;MAAM;QACf,MAAA,EAAA,CAAE,CAAA,+BAAA,CAAA,GAAA;wBAIO,EAPP,YAAK,CAIf,WAGiB,KAAA,QAAA,WAAA;OAFd,aAAa,MAAK;OAEZ;UACT,WAIO,KAAA,QAAA,YAAA,EAFE,KAAI,SAEN,CADL,YAA0B,MAAA,8BAAA,CAAA,CAAA,CAAA,CAAA,CAAA;;;4BAdhB,CAFhB,YAEgB,MAAA,aAAA,GAAA,EAFD,IAAG,WAAU,GAAA;6BACL,CAArB,WAAqB,KAAA,QAAA,WAAA,EAAR,KAAI,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"ScalarPopover.vue.script.js","names":["$props"],"sources":["../../../src/components/ScalarPopover/ScalarPopover.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Scalar Popover component\n *\n * A floating panel that appears when a trigger element is clicked.\n * Built on HeadlessUI Popover with Floating UI positioning.\n *\n * @example\n * <ScalarPopover>\n * <button>Open</button>\n * <template #popover=\"{ close }\">Popover content</template>\n * </ScalarPopover>\n */\nexport default {}\n</script>\n<script setup lang=\"ts\">\nimport { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'\nimport { useBindCx } from '@scalar/use-hooks/useBindCx'\n\nimport { ScalarFloating, type ScalarFloatingOptions } from '../ScalarFloating'\nimport type { Slots } from './types'\n\ndefineProps<\n {\n /** Automatically focus the popover panel when it opens */\n focus?: boolean\n } & ScalarFloatingOptions\n>()\n\ndefineSlots<Slots>()\n\ndefineOptions({ inheritAttrs: false })\nconst { cx } = useBindCx()\n</script>\n<template>\n <Popover\n v-slot=\"{ open }\"\n as=\"template\">\n <ScalarFloating v-bind=\"$props\">\n <PopoverButton as=\"template\">\n <slot :open=\"open\" />\n </PopoverButton>\n <template #floating=\"{ width, height }\">\n <PopoverPanel\n v-slot=\"{ close }\"\n :focus=\"focus\"\n :style=\"{ width, height }\"\n v-bind=\"\n cx(\n 'relative flex flex-col rounded-xl bg-b-1 dark:bg-b-1.5 p-0.75 shadow-md inset-shadow-border',\n )\n \">\n <slot\n :close=\"() => close()\"\n name=\"popover\"\n :open=\"open\" />\n </PopoverPanel>\n </template>\n </ScalarFloating>\n </Popover>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAgCA,MAAM,EAAE,OAAO,UAAU;;uBAGvB,YAwBU,MAAA,OAAA,GAAA,EAtBR,IAAG,WAAU,GAAA;sBAqBI,EAtBP,WAAI,CAEd,YAoBiB,MAAA,sBAAA,GAAA,eAAA,mBApBOA,KAAAA,MAAM,CAAA,GAAA;KAIjB,UAAQ,SAcF,EAdM,OAAO,aAAM,CAClC,YAae,MAAA,YAAA,GAbf,WAae;MAXZ,OAAO,QAAA;MACP,OAAK;OAAI;OAAO;MAAM;QACF,MAAA,EAAA,CAAE,CAAA,6FAAA,CAAA,GAAA;wBAQN,EAXP,YAAK,CAQf,WAGiB,KAAA,QAAA,WAAA;OAFd,aAAa,MAAK;OAEZ;;;;4BAdG,CAFhB,YAEgB,MAAA,aAAA,GAAA,EAFD,IAAG,WAAU,GAAA;6BACL,CAArB,WAAqB,KAAA,QAAA,WAAA,EAAR,KAAI,CAAA,CAAA,CAAA"}
@@ -10,10 +10,5 @@ export type Slots = {
10
10
  /** A callback to close the popover */
11
11
  close: () => void;
12
12
  }): unknown;
13
- /** Overrides the popover backdrop */
14
- backdrop?(props: {
15
- /** Whether or not the popover is open */
16
- open: boolean;
17
- }): unknown;
18
13
  };
19
14
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarPopover/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG;IAClB,OAAO,CAAC,KAAK,EAAE;QACb,yCAAyC;QACzC,IAAI,EAAE,OAAO,CAAA;KACd,GAAG,OAAO,CAAA;IACX,2BAA2B;IAC3B,OAAO,CAAC,KAAK,EAAE;QACb,yCAAyC;QACzC,IAAI,EAAE,OAAO,CAAA;QACb,sCAAsC;QACtC,KAAK,EAAE,MAAM,IAAI,CAAA;KAClB,GAAG,OAAO,CAAA;IACX,qCAAqC;IACrC,QAAQ,CAAC,CAAC,KAAK,EAAE;QACf,yCAAyC;QACzC,IAAI,EAAE,OAAO,CAAA;KACd,GAAG,OAAO,CAAA;CACZ,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/ScalarPopover/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG;IAClB,OAAO,CAAC,KAAK,EAAE;QACb,yCAAyC;QACzC,IAAI,EAAE,OAAO,CAAA;KACd,GAAG,OAAO,CAAA;IACX,2BAA2B;IAC3B,OAAO,CAAC,KAAK,EAAE;QACb,yCAAyC;QACzC,IAAI,EAAE,OAAO,CAAA;QACb,sCAAsC;QACtC,KAAK,EAAE,MAAM,IAAI,CAAA;KAClB,GAAG,OAAO,CAAA;CACZ,CAAA"}
package/dist/style.css CHANGED
@@ -783,6 +783,10 @@
783
783
  left: 0;
784
784
  }
785
785
 
786
+ .scalar-app .left-1\.75 {
787
+ left: 7px;
788
+ }
789
+
786
790
  .scalar-app .left-1\/2 {
787
791
  left: 50%;
788
792
  }
@@ -791,10 +795,6 @@
791
795
  left: 8px;
792
796
  }
793
797
 
794
- .scalar-app .left-2\.5 {
795
- left: 10px;
796
- }
797
-
798
798
  .scalar-app .left-3 {
799
799
  left: 12px;
800
800
  }
@@ -1035,6 +1035,10 @@
1035
1035
  margin-bottom: 0;
1036
1036
  }
1037
1037
 
1038
+ .scalar-app .mb-0\.75 {
1039
+ margin-bottom: 3px;
1040
+ }
1041
+
1038
1042
  .scalar-app .-ml-0\.5 {
1039
1043
  margin-left: -2px;
1040
1044
  }
@@ -1944,10 +1948,6 @@
1944
1948
  }
1945
1949
  }
1946
1950
 
1947
- .scalar-app .bg-red {
1948
- background-color: var(--scalar-color-red);
1949
- }
1950
-
1951
1951
  .scalar-app .bg-sidebar-b-1 {
1952
1952
  background-color: var(--scalar-sidebar-background-1, var(--scalar-background-1));
1953
1953
  }
@@ -2165,10 +2165,6 @@
2165
2165
  padding-block: 8px;
2166
2166
  }
2167
2167
 
2168
- .scalar-app .py-2\.5 {
2169
- padding-block: 10px;
2170
- }
2171
-
2172
2168
  .scalar-app .py-3 {
2173
2169
  padding-block: 12px;
2174
2170
  }
@@ -2201,8 +2197,8 @@
2201
2197
  padding-right: 6px;
2202
2198
  }
2203
2199
 
2204
- .scalar-app .pr-3 {
2205
- padding-right: 12px;
2200
+ .scalar-app .pr-1\.75 {
2201
+ padding-right: 7px;
2206
2202
  }
2207
2203
 
2208
2204
  .scalar-app .pr-6 {
@@ -2229,8 +2225,8 @@
2229
2225
  padding-left: 12px;
2230
2226
  }
2231
2227
 
2232
- .scalar-app .pl-8 {
2233
- padding-left: 32px;
2228
+ .scalar-app .pl-7\.25 {
2229
+ padding-left: 29px;
2234
2230
  }
2235
2231
 
2236
2232
  .scalar-app .pl-\[100\%\] {
@@ -2499,6 +2495,11 @@
2499
2495
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2500
2496
  }
2501
2497
 
2498
+ .scalar-app .inset-shadow-border {
2499
+ --tw-inset-shadow: inset 0 0 0 var(--scalar-border-width) var(--scalar-border-color);
2500
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2501
+ }
2502
+
2502
2503
  .scalar-app .outline {
2503
2504
  outline-style: var(--tw-outline-style);
2504
2505
  outline-width: 1px;
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "url": "git+https://github.com/scalar/scalar.git",
11
11
  "directory": "packages/components"
12
12
  },
13
- "version": "0.30.6",
13
+ "version": "0.31.0",
14
14
  "engines": {
15
15
  "node": ">=22"
16
16
  },
@@ -217,10 +217,10 @@
217
217
  "@headlessui/tailwindcss": "^0.2.2",
218
218
  "@headlessui/vue": "1.7.23",
219
219
  "@scalar/code-highlight": "0.4.8",
220
- "@scalar/helpers": "0.16.0",
220
+ "@scalar/helpers": "0.16.2",
221
221
  "@scalar/icons": "0.7.6",
222
- "@scalar/themes": "0.18.1",
223
- "@scalar/use-hooks": "0.4.17",
222
+ "@scalar/themes": "0.19.0",
223
+ "@scalar/use-hooks": "0.4.19",
224
224
  "@vueuse/core": "13.9.0",
225
225
  "cva": "1.0.0-beta.4",
226
226
  "radix-vue": "^1.9.17",