@sewadah/selaras 0.2.0 → 0.3.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 (46) hide show
  1. package/README.md +36 -7
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +18 -15
  4. package/dist/runtime/components/Badge.d.vue.ts +1 -1
  5. package/dist/runtime/components/Badge.vue.d.ts +1 -1
  6. package/dist/runtime/components/ContentToc.vue +14 -7
  7. package/dist/runtime/components/FileUpload.vue +1 -1
  8. package/dist/runtime/components/NavigationMenu.vue +2 -0
  9. package/dist/runtime/components/PinInput.vue +1 -1
  10. package/dist/runtime/components/ProsePre.d.vue.ts +4 -2
  11. package/dist/runtime/components/ProsePre.vue +9 -3
  12. package/dist/runtime/components/ProsePre.vue.d.ts +4 -2
  13. package/dist/runtime/default-colors.css +1 -1
  14. package/dist/runtime/internal/ComboboxSelectBase.vue +1 -1
  15. package/dist/runtime/structural.css +1 -1
  16. package/dist/runtime/theme/avatar.js +7 -7
  17. package/dist/runtime/theme/badge.js +2 -2
  18. package/dist/runtime/theme/checkbox.js +1 -1
  19. package/dist/runtime/theme/date-picker.js +1 -1
  20. package/dist/runtime/theme/file-upload.js +2 -2
  21. package/dist/runtime/theme/icon.js +1 -1
  22. package/dist/runtime/theme/input-number.js +1 -1
  23. package/dist/runtime/theme/input.js +1 -1
  24. package/dist/runtime/theme/pin-input.js +1 -1
  25. package/dist/runtime/theme/progress.js +2 -2
  26. package/dist/runtime/theme/prose.d.ts +6 -0
  27. package/dist/runtime/theme/prose.js +2 -0
  28. package/dist/runtime/theme/radio-group.js +4 -4
  29. package/dist/runtime/theme/rating.js +1 -1
  30. package/dist/runtime/theme/select.js +2 -2
  31. package/dist/runtime/theme/separator.js +1 -1
  32. package/dist/runtime/theme/slider.js +2 -2
  33. package/dist/runtime/theme/splitter-resize-handle.js +1 -1
  34. package/dist/runtime/theme/switch.js +1 -1
  35. package/dist/runtime/theme/textarea.js +1 -1
  36. package/dist/runtime/utils/color-registry.d.ts +3 -1
  37. package/dist/runtime/utils/color-registry.js +4 -0
  38. package/dist/runtime/utils/file-icons.d.ts +8 -0
  39. package/dist/runtime/utils/file-icons.js +131 -0
  40. package/dist/runtime/utils/functional-tokens.d.ts +1 -1
  41. package/dist/runtime/utils/functional-tokens.js +1 -1
  42. package/dist/runtime/utils/navigation-menu.d.ts +3 -0
  43. package/dist/runtime/utils/seed-colors.d.ts +2 -1
  44. package/dist/runtime/utils/seed-colors.js +24 -16
  45. package/dist/tokens/default-colors.tokens.json +100 -100
  46. package/package.json +20 -9
package/README.md CHANGED
@@ -96,6 +96,26 @@ Every component is now auto-imported and ready to use:
96
96
  </SButton>
97
97
  ```
98
98
 
99
+ ## Theming
100
+
101
+ Selaras is CSS-first for design values.
102
+
103
+ For normal theme changes, override the public `--selaras-*` CSS variables or
104
+ the Selaras foundation palettes in Tailwind `@theme`. You do not need
105
+ `nuxt.config.ts` to change built-in roles such as `primary`, `warning`,
106
+ `danger`, or `neutral`.
107
+
108
+ Use `selaras.theme.colors` in `nuxt.config.ts` when you must register a new
109
+ role name, such as `tertiary`, or when you intentionally want to author a
110
+ complete build-time recipe.
111
+
112
+ `defineColorFromSeed()` is an optional accessibility-oriented generator. The
113
+ supplied color remains the exact resting solid fill; Selaras derives readable
114
+ content, interaction states, text, borders, focus, and essential indicators
115
+ around it. Use `defineColor()` when you need to author every leaf yourself.
116
+
117
+ See the full [Theming guide](./docs/content/overview/theming.md).
118
+
99
119
  ## Contribution
100
120
 
101
121
  <details>
@@ -105,14 +125,14 @@ Every component is now auto-imported and ready to use:
105
125
  # Install dependencies
106
126
  npm install
107
127
 
108
- # Generate type stubs
109
- npm run dev:prepare
128
+ # Generate type stubs and prepare the docs site
129
+ npm run docs:prepare
110
130
 
111
- # Develop with the playground (component docs site)
112
- npm run dev
131
+ # Develop with the docs site (documentation + component showcase)
132
+ npm run docs:dev
113
133
 
114
- # Build the playground
115
- npm run dev:build
134
+ # Generate the static docs site
135
+ npm run docs:generate
116
136
 
117
137
  # Type-check
118
138
  npm run test:types
@@ -128,8 +148,17 @@ Every component is now auto-imported and ready to use:
128
148
  # Requires Bun for the temporary consumer's dependency installation
129
149
  npm run test:compat
130
150
 
131
- # Release new version
151
+ # Release new versions (selaras, docs layer, or both)
132
152
  npm run release
153
+ npm run release:selaras
154
+ npm run release:docs
155
+
156
+ # Each package has its own version stream, so one run can bump them at
157
+ # different levels - Selaras major alongside a docs patch, for example.
158
+ # The release workflow exposes per-package bump/version inputs for this.
159
+ # Locally, drive each half through its own env:
160
+ RELEASE_BUMP=major npm run release:selaras
161
+ RELEASE_BUMP=patch npm run release:docs
133
162
  ```
134
163
 
135
164
  </details>
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "selaras",
3
3
  "configKey": "selaras",
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -6,19 +6,19 @@ import { builtinColorNames, createColorRegistry, generateColorRoleCss } from '..
6
6
  const foundationPaletteByRole = {
7
7
  primary: "indigo",
8
8
  secondary: "plum",
9
- success: "emerald",
9
+ success: "green",
10
10
  info: "blue",
11
- warning: "amber",
11
+ warning: "yellow",
12
12
  danger: "red",
13
13
  neutral: "gray"
14
14
  };
15
15
  const fillShadesByRole = {
16
16
  primary: { light: [500, 600, 700], dark: [400, 300, 200] },
17
17
  secondary: { light: [600, 700, 800], dark: [400, 300, 200] },
18
- success: { light: [700, 800, 900], dark: [500, 400, 300] },
18
+ success: { light: [500, 600, 700], dark: [500, 400, 300] },
19
19
  info: { light: [600, 700, 800], dark: [500, 400, 300] },
20
- warning: { light: [700, 800, 900], dark: [500, 400, 300] },
21
- danger: { light: [600, 700, 800], dark: [500, 400, 300] },
20
+ warning: { light: [500, 600, 700], dark: [500, 400, 300] },
21
+ danger: { light: [500, 600, 700], dark: [500, 400, 300] },
22
22
  neutral: { light: [950, 900, 800], dark: [200, 100, 50] }
23
23
  };
24
24
  function createBuiltinColorRegistry(classPrefix) {
@@ -26,29 +26,32 @@ function createBuiltinColorRegistry(classPrefix) {
26
26
  const recipes = Object.fromEntries(builtinColorNames.map((role) => {
27
27
  const mode = (dark) => {
28
28
  const neutral = role === "neutral";
29
- const warning = role === "warning";
29
+ const brightIntent = role === "success" || role === "warning" || role === "danger";
30
30
  const modeName = dark ? "dark" : "light";
31
31
  const [fillShade, hoverShade, pressedShade] = fillShadesByRole[role][modeName];
32
- const textShade = warning || role === "success" ? 800 : role === "info" || role === "danger" ? 700 : fillShade;
32
+ const textShade = brightIntent ? 800 : role === "info" ? 700 : fillShade;
33
33
  const fill = foundation(role, fillShade);
34
- const hover = foundation(role, hoverShade);
35
- const pressed = foundation(role, pressedShade);
34
+ const hover = brightIntent ? `color-mix(in oklab, ${fill} ${!dark && role === "danger" ? 98 : 94}%, ${dark ? "white" : "black"})` : foundation(role, hoverShade);
35
+ const pressed = brightIntent ? `color-mix(in oklab, ${fill} ${!dark && role === "danger" ? 96 : 88}%, ${dark ? "white" : "black"})` : foundation(role, pressedShade);
36
36
  const text = foundation(role, neutral ? dark ? 50 : 950 : dark ? 300 : textShade);
37
- const subtle = neutral ? foundation(role, dark ? 900 : 100) : dark ? `color-mix(in oklab, ${fill} 24%, var(--selaras-resolved-surface-default))` : foundation(role, 100);
37
+ const subtle = neutral ? foundation(role, dark ? 900 : 100) : dark ? `color-mix(in oklab, ${fill} ${brightIntent ? 16 : 24}%, var(--selaras-resolved-surface-default))` : foundation(role, brightIntent ? 50 : 100);
38
+ const indicatorShade = dark ? 400 : role === "success" || role === "warning" ? 700 : role === "danger" ? 500 : fillShade;
39
+ const indicator = neutral ? foundation(role, 500) : foundation(role, indicatorShade);
38
40
  return {
39
41
  fill,
40
42
  fillHover: hover,
41
43
  fillPressed: pressed,
42
- onFill: foundation("neutral", dark ? 950 : 25),
44
+ onFill: foundation("neutral", brightIntent ? 950 : dark ? 950 : 25),
45
+ indicator,
43
46
  subtle,
44
- subtleHover: dark ? `color-mix(in oklab, ${foundation(role, 500)} 32%, var(--selaras-resolved-surface-default))` : `color-mix(in oklab, ${subtle} 94%, ${text})`,
45
- subtlePressed: dark ? `color-mix(in oklab, ${foundation(role, 500)} 40%, var(--selaras-resolved-surface-default))` : `color-mix(in oklab, ${subtle} 90%, ${text})`,
47
+ subtleHover: brightIntent ? `color-mix(in oklab, ${subtle} 96%, ${text})` : dark ? `color-mix(in oklab, ${foundation(role, 500)} 32%, var(--selaras-resolved-surface-default))` : `color-mix(in oklab, ${subtle} 94%, ${text})`,
48
+ subtlePressed: brightIntent ? `color-mix(in oklab, ${subtle} 92%, ${text})` : dark ? `color-mix(in oklab, ${foundation(role, 500)} 40%, var(--selaras-resolved-surface-default))` : `color-mix(in oklab, ${subtle} 90%, ${text})`,
46
49
  onSubtle: text,
47
50
  text,
48
51
  textHover: foundation(role, neutral ? dark ? 100 : 900 : dark ? 200 : Math.min(textShade + 100, 950)),
49
52
  textPressed: foundation(role, neutral ? dark ? 200 : 800 : dark ? 100 : Math.min(textShade + 200, 950)),
50
- border: neutral ? foundation(role, 500) : fill,
51
- focus: text
53
+ border: indicator,
54
+ focus: brightIntent ? indicator : text
52
55
  };
53
56
  };
54
57
  return [role, { light: mode(false), dark: mode(true) }];
@@ -8,7 +8,7 @@ export interface BadgeProps {
8
8
  label?: string;
9
9
  icon?: string;
10
10
  trailingIcon?: string;
11
- /** A status circle. Inline dots use the badge foreground; standalone dots use the role text color. Supply an accessible name when no label is visible. */
11
+ /** A status circle. Inline dots use the badge foreground; standalone dots use the role indicator. Supply an accessible name when no label is visible. */
12
12
  dot?: boolean;
13
13
  color?: ColorRole;
14
14
  variant?: BadgeVariants['variant'];
@@ -8,7 +8,7 @@ export interface BadgeProps {
8
8
  label?: string;
9
9
  icon?: string;
10
10
  trailingIcon?: string;
11
- /** A status circle. Inline dots use the badge foreground; standalone dots use the role text color. Supply an accessible name when no label is visible. */
11
+ /** A status circle. Inline dots use the badge foreground; standalone dots use the role indicator. Supply an accessible name when no label is visible. */
12
12
  dot?: boolean;
13
13
  color?: ColorRole;
14
14
  variant?: BadgeVariants['variant'];
@@ -119,27 +119,34 @@ function buildRailPath(links, height) {
119
119
  const x2 = RAIL_X_OUTER + index * indentStep;
120
120
  return Math.round(clamp(x2, RAIL_X_OUTER, RAIL_X_INNER_MAX));
121
121
  };
122
+ const curveHalf = RAIL_CURVE_SPAN / 2;
122
123
  let x = xForDepth(items[0]?.depth ?? baseDepth);
124
+ let yPath = 0;
123
125
  let yPrev = 0;
124
126
  let d = `M ${x} 0`;
125
127
  for (const item of items) {
126
128
  const y = clamp(item.y, 0, height);
127
129
  const xNext = xForDepth(item.depth);
128
130
  if (xNext === x) {
129
- if (y > yPrev)
131
+ if (y > yPath) {
130
132
  d += ` L ${x} ${y}`;
131
- yPrev = Math.max(yPrev, y);
133
+ yPath = y;
134
+ }
135
+ yPrev = y;
132
136
  continue;
133
137
  }
134
- const y0 = clamp(y - RAIL_CURVE_SPAN, yPrev, height);
135
- const midY = (y0 + y) / 2;
136
- if (y0 > yPrev)
138
+ const midY = (yPrev + y) / 2;
139
+ const y0 = clamp(midY - curveHalf, yPath, y);
140
+ const y1 = clamp(midY + curveHalf, y0, y);
141
+ const controlY = (y0 + y1) / 2;
142
+ if (y0 > yPath)
137
143
  d += ` L ${x} ${y0}`;
138
- d += ` C ${x} ${midY} ${xNext} ${midY} ${xNext} ${y}`;
144
+ d += ` C ${x} ${controlY} ${xNext} ${controlY} ${xNext} ${y1}`;
139
145
  x = xNext;
146
+ yPath = y1;
140
147
  yPrev = y;
141
148
  }
142
- if (height > yPrev)
149
+ if (height > yPath)
143
150
  d += ` L ${x} ${height}`;
144
151
  return d;
145
152
  }
@@ -202,7 +202,7 @@ const removeButtonSize = computed(() => ({ sm: "sm", md: "sm", lg: "md" })[effec
202
202
  </script>
203
203
 
204
204
  <template>
205
- <div :data-selaras-color="effectiveColor" v-bind="rootProps">
205
+ <div :data-selaras-color="fileUploadInvalid ? 'danger' : effectiveColor" v-bind="rootProps">
206
206
  <button
207
207
  ref="dropzoneEl"
208
208
  type="button"
@@ -122,6 +122,7 @@ function onSelect(item, event) {
122
122
  <component
123
123
  :is="child.to ? NuxtLink : 'button'" :to="child.to" :type="child.to ? void 0 : 'button'"
124
124
  :disabled="child.to ? void 0 : child.disabled" v-bind="childLinkProps(child)"
125
+ :target="child.target" :rel="child.rel" :aria-label="child.ariaLabel"
125
126
  :aria-disabled="child.to && child.disabled ? 'true' : void 0" @click="onSelect(child, $event)"
126
127
  >
127
128
  <slot :name="slotName(child, '')" :item="child" :active="isActive(child)">
@@ -144,6 +145,7 @@ function onSelect(item, event) {
144
145
  <component
145
146
  :is="item.to ? NuxtLink : 'button'" :to="item.to" :type="item.to ? void 0 : 'button'"
146
147
  :disabled="item.to ? void 0 : item.disabled" v-bind="linkProps(item)"
148
+ :target="item.target" :rel="item.rel" :aria-label="item.ariaLabel"
147
149
  :aria-disabled="item.to && item.disabled ? 'true' : void 0" @click="onSelect(item, $event)"
148
150
  >
149
151
  <slot :name="slotName(item, '')" :item="item" :active="isActive(item)">
@@ -60,7 +60,7 @@ const inputProps = computed(() => mergeProps(resolveSlot(ui.value.input, props.u
60
60
  :aria-invalid="pinInputInvalid || void 0"
61
61
  :aria-describedby="describedBy"
62
62
  :aria-labelledby="labelledBy"
63
- :data-selaras-color="effectiveColor"
63
+ :data-selaras-color="pinInputInvalid ? 'danger' : effectiveColor"
64
64
  v-bind="rootProps"
65
65
  @update:model-value="(value) => emit('update:modelValue', value)"
66
66
  @complete="(value) => emit('complete', value)"
@@ -2,12 +2,14 @@ export interface ProsePreProps {
2
2
  code?: string;
3
3
  language?: string;
4
4
  filename?: string;
5
+ /** Overrides the file-type icon resolved from `filename`/`language`. */
6
+ icon?: string;
5
7
  highlights?: number[];
6
8
  meta?: string;
7
9
  }
8
- declare var __VLS_13: {};
10
+ declare var __VLS_18: {};
9
11
  type __VLS_Slots = {} & {
10
- default?: (props: typeof __VLS_13) => any;
12
+ default?: (props: typeof __VLS_18) => any;
11
13
  };
12
14
  declare const __VLS_base: import("vue").DefineComponent<ProsePreProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ProsePreProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
15
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -2,18 +2,22 @@
2
2
  import { computed, ref } from "vue";
3
3
  import { useIcons } from "../composables/use-icons";
4
4
  import { proseTheme } from "../theme/prose";
5
+ import { resolveFileIcon } from "../utils/file-icons";
5
6
  import { resolveSlot, useComponentTheme, useRootProps } from "../utils/ui";
6
7
  import Badge from "./Badge.vue";
7
8
  import Button from "./Button.vue";
9
+ import Icon from "./Icon.vue";
8
10
  defineOptions({ inheritAttrs: false });
9
11
  const props = defineProps({
10
12
  code: { type: String, required: false },
11
13
  language: { type: String, required: false },
12
14
  filename: { type: String, required: false },
15
+ icon: { type: String, required: false },
13
16
  highlights: { type: Array, required: false },
14
17
  meta: { type: String, required: false }
15
18
  });
16
19
  const icons = useIcons();
20
+ const fileIcon = computed(() => props.icon ?? resolveFileIcon(props.language, props.filename));
17
21
  const theme = useComponentTheme("prose", proseTheme);
18
22
  const ui = computed(() => theme.value());
19
23
  const preProps = useRootProps(() => ui.value.pre, () => void 0);
@@ -32,9 +36,11 @@ async function copy() {
32
36
  <template>
33
37
  <div v-bind="resolveSlot(ui.preWrapper, void 0)">
34
38
  <div v-if="filename || language || code" v-bind="resolveSlot(ui.preHeader, void 0)">
35
- <span v-if="filename" v-bind="resolveSlot(ui.preFilename, void 0)">{{ filename }}</span>
36
- <Badge v-else-if="language" :label="language" size="sm" variant="outline" />
37
- <span v-else />
39
+ <span v-bind="resolveSlot(ui.preLabel, void 0)">
40
+ <Icon v-if="fileIcon" :name="fileIcon" v-bind="resolveSlot(ui.preIcon, void 0)" />
41
+ <span v-if="filename" v-bind="resolveSlot(ui.preFilename, void 0)">{{ filename }}</span>
42
+ <Badge v-else-if="language" :label="language" size="sm" variant="outline" />
43
+ </span>
38
44
  <Button
39
45
  v-if="code"
40
46
  v-bind="resolveSlot(ui.preCopyButton, void 0)"
@@ -2,12 +2,14 @@ export interface ProsePreProps {
2
2
  code?: string;
3
3
  language?: string;
4
4
  filename?: string;
5
+ /** Overrides the file-type icon resolved from `filename`/`language`. */
6
+ icon?: string;
5
7
  highlights?: number[];
6
8
  meta?: string;
7
9
  }
8
- declare var __VLS_13: {};
10
+ declare var __VLS_18: {};
9
11
  type __VLS_Slots = {} & {
10
- default?: (props: typeof __VLS_13) => any;
12
+ default?: (props: typeof __VLS_18) => any;
11
13
  };
12
14
  declare const __VLS_base: import("vue").DefineComponent<ProsePreProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ProsePreProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
15
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1 +1 @@
1
- @theme static{--color-selaras-amber-50:oklch(0.985 0.022 88);--color-selaras-amber-100:oklch(0.96 0.055 88);--color-selaras-amber-200:oklch(0.915 0.105 88);--color-selaras-amber-300:oklch(0.86 0.145 88);--color-selaras-amber-400:oklch(0.81 0.165 88);--color-selaras-amber-500:oklch(0.755 0.165 88);--color-selaras-amber-600:oklch(0.665 0.155 88);--color-selaras-amber-700:oklch(0.565 0.135 88);--color-selaras-amber-800:oklch(0.465 0.11 88);--color-selaras-amber-900:oklch(0.375 0.085 88);--color-selaras-amber-950:oklch(0.255 0.055 88);--color-selaras-blue-50:oklch(0.975 0.018 245);--color-selaras-blue-100:oklch(0.945 0.04 245);--color-selaras-blue-200:oklch(0.895 0.075 245);--color-selaras-blue-300:oklch(0.82 0.115 245);--color-selaras-blue-400:oklch(0.715 0.155 245);--color-selaras-blue-500:oklch(0.62 0.175 245);--color-selaras-blue-600:oklch(0.535 0.165 245);--color-selaras-blue-700:oklch(0.455 0.145 245);--color-selaras-blue-800:oklch(0.375 0.115 245);--color-selaras-blue-900:oklch(0.3 0.085 245);--color-selaras-blue-950:oklch(0.215 0.055 245);--color-selaras-emerald-50:oklch(0.98 0.02 148);--color-selaras-emerald-100:oklch(0.95 0.045 148);--color-selaras-emerald-200:oklch(0.895 0.08 148);--color-selaras-emerald-300:oklch(0.82 0.12 148);--color-selaras-emerald-400:oklch(0.735 0.155 148);--color-selaras-emerald-500:oklch(0.64 0.175 148);--color-selaras-emerald-600:oklch(0.555 0.16 148);--color-selaras-emerald-700:oklch(0.47 0.14 148);--color-selaras-emerald-800:oklch(0.39 0.115 148);--color-selaras-emerald-900:oklch(0.315 0.085 148);--color-selaras-emerald-950:oklch(0.225 0.055 148);--color-selaras-gray-25:oklch(0.995 0.0015 280);--color-selaras-gray-50:oklch(0.98 0.003 280);--color-selaras-gray-100:oklch(0.945 0.0065 280);--color-selaras-gray-200:oklch(0.9 0.01 280);--color-selaras-gray-300:oklch(0.84 0.014 280);--color-selaras-gray-400:oklch(0.7 0.018 280);--color-selaras-gray-500:oklch(0.555 0.02 280);--color-selaras-gray-600:oklch(0.445 0.019 280);--color-selaras-gray-700:oklch(0.365 0.017 280);--color-selaras-gray-800:oklch(0.275 0.014 280);--color-selaras-gray-900:oklch(0.205 0.011 280);--color-selaras-gray-950:oklch(0.145 0.008 280);--color-selaras-indigo-50:oklch(0.97 0.012 279.99);--color-selaras-indigo-100:oklch(0.93 0.028 279.99);--color-selaras-indigo-200:oklch(0.86 0.055 279.99);--color-selaras-indigo-300:oklch(0.78 0.1 279.99);--color-selaras-indigo-400:oklch(0.64 0.165 279.99);--color-selaras-indigo-500:oklch(0.4755 0.2026 279.99);--color-selaras-indigo-600:oklch(0.415 0.185 279.99);--color-selaras-indigo-700:oklch(0.355 0.158 279.99);--color-selaras-indigo-800:oklch(0.295 0.128 279.99);--color-selaras-indigo-900:oklch(0.235 0.095 279.99);--color-selaras-indigo-950:oklch(0.17 0.06 279.99);--color-selaras-plum-50:oklch(0.975 0.012 325);--color-selaras-plum-100:oklch(0.945 0.03 325);--color-selaras-plum-200:oklch(0.89 0.06 325);--color-selaras-plum-300:oklch(0.81 0.1 325);--color-selaras-plum-400:oklch(0.69 0.145 325);--color-selaras-plum-500:oklch(0.565 0.175 325);--color-selaras-plum-600:oklch(0.495 0.165 325);--color-selaras-plum-700:oklch(0.42 0.145 325);--color-selaras-plum-800:oklch(0.345 0.115 325);--color-selaras-plum-900:oklch(0.275 0.085 325);--color-selaras-plum-950:oklch(0.19 0.055 325);--color-selaras-red-50:oklch(0.975 0.015 28);--color-selaras-red-100:oklch(0.945 0.035 28);--color-selaras-red-200:oklch(0.89 0.07 28);--color-selaras-red-300:oklch(0.805 0.12 28);--color-selaras-red-400:oklch(0.7 0.175 28);--color-selaras-red-500:oklch(0.6 0.205 28);--color-selaras-red-600:oklch(0.525 0.195 28);--color-selaras-red-700:oklch(0.445 0.17 28);--color-selaras-red-800:oklch(0.365 0.135 28);--color-selaras-red-900:oklch(0.295 0.1 28);--color-selaras-red-950:oklch(0.205 0.065 28)}@layer theme{:root,[data-selaras-theme]{--_selaras-default-surface-default:--theme(--color-selaras-gray-25);--_selaras-default-surface-elevated:--theme(--color-selaras-gray-50);--_selaras-default-surface-inverted:--theme(--color-selaras-gray-950);--_selaras-default-text-default:--theme(--color-selaras-gray-950);--_selaras-default-text-muted:--theme(--color-selaras-gray-600);--_selaras-default-text-inverted:--theme(--color-selaras-gray-50);--_selaras-default-border-default:--theme(--color-selaras-gray-200);--_selaras-default-border-muted:--theme(--color-selaras-gray-100);--_selaras-default-border-hover:--theme(--color-selaras-gray-300)}:root.dark,:root.dark [data-selaras-theme]:where(:not([data-selaras-mode]),[data-selaras-mode=root]),[data-selaras-theme]:where([data-selaras-mode=dark]){--_selaras-default-surface-default:--theme(--color-selaras-gray-950);--_selaras-default-surface-elevated:--theme(--color-selaras-gray-900);--_selaras-default-surface-inverted:--theme(--color-selaras-gray-50);--_selaras-default-text-default:--theme(--color-selaras-gray-50);--_selaras-default-text-muted:--theme(--color-selaras-gray-400);--_selaras-default-text-inverted:--theme(--color-selaras-gray-950);--_selaras-default-border-default:--theme(--color-selaras-gray-800);--_selaras-default-border-muted:--theme(--color-selaras-gray-900);--_selaras-default-border-hover:--theme(--color-selaras-gray-700)}}
1
+ @theme static{--color-selaras-blue-50:oklch(0.975 0.018 245);--color-selaras-blue-100:oklch(0.945 0.04 245);--color-selaras-blue-200:oklch(0.895 0.075 245);--color-selaras-blue-300:oklch(0.82 0.115 245);--color-selaras-blue-400:oklch(0.715 0.155 245);--color-selaras-blue-500:oklch(0.62 0.175 245);--color-selaras-blue-600:oklch(0.535 0.165 245);--color-selaras-blue-700:oklch(0.455 0.145 245);--color-selaras-blue-800:oklch(0.375 0.115 245);--color-selaras-blue-900:oklch(0.3 0.085 245);--color-selaras-blue-950:oklch(0.215 0.055 245);--color-selaras-gray-25:oklch(0.995 0.0015 280);--color-selaras-gray-50:oklch(0.98 0.003 280);--color-selaras-gray-100:oklch(0.945 0.0065 280);--color-selaras-gray-200:oklch(0.9 0.01 280);--color-selaras-gray-300:oklch(0.84 0.014 280);--color-selaras-gray-400:oklch(0.7 0.018 280);--color-selaras-gray-500:oklch(0.555 0.02 280);--color-selaras-gray-600:oklch(0.445 0.019 280);--color-selaras-gray-700:oklch(0.365 0.017 280);--color-selaras-gray-800:oklch(0.275 0.014 280);--color-selaras-gray-900:oklch(0.205 0.011 280);--color-selaras-gray-950:oklch(0.145 0.008 280);--color-selaras-green-50:oklch(0.982 0.018 155.826);--color-selaras-green-100:oklch(0.962 0.044 156.743);--color-selaras-green-200:oklch(0.925 0.084 155.995);--color-selaras-green-300:oklch(0.871 0.15 154.449);--color-selaras-green-400:oklch(0.792 0.209 151.711);--color-selaras-green-500:oklch(0.723 0.219 149.579);--color-selaras-green-600:oklch(0.627 0.194 149.214);--color-selaras-green-700:oklch(0.527 0.154 150.069);--color-selaras-green-800:oklch(0.448 0.119 151.328);--color-selaras-green-900:oklch(0.393 0.095 152.535);--color-selaras-green-950:oklch(0.266 0.065 152.934);--color-selaras-indigo-50:oklch(0.97 0.012 279.99);--color-selaras-indigo-100:oklch(0.93 0.028 279.99);--color-selaras-indigo-200:oklch(0.86 0.055 279.99);--color-selaras-indigo-300:oklch(0.78 0.1 279.99);--color-selaras-indigo-400:oklch(0.64 0.165 279.99);--color-selaras-indigo-500:oklch(0.4755 0.2026 279.99);--color-selaras-indigo-600:oklch(0.415 0.185 279.99);--color-selaras-indigo-700:oklch(0.355 0.158 279.99);--color-selaras-indigo-800:oklch(0.295 0.128 279.99);--color-selaras-indigo-900:oklch(0.235 0.095 279.99);--color-selaras-indigo-950:oklch(0.17 0.06 279.99);--color-selaras-plum-50:oklch(0.975 0.012 325);--color-selaras-plum-100:oklch(0.945 0.03 325);--color-selaras-plum-200:oklch(0.89 0.06 325);--color-selaras-plum-300:oklch(0.81 0.1 325);--color-selaras-plum-400:oklch(0.69 0.145 325);--color-selaras-plum-500:oklch(0.565 0.175 325);--color-selaras-plum-600:oklch(0.495 0.165 325);--color-selaras-plum-700:oklch(0.42 0.145 325);--color-selaras-plum-800:oklch(0.345 0.115 325);--color-selaras-plum-900:oklch(0.275 0.085 325);--color-selaras-plum-950:oklch(0.19 0.055 325);--color-selaras-red-50:oklch(0.971 0.013 17.38);--color-selaras-red-100:oklch(0.936 0.032 17.717);--color-selaras-red-200:oklch(0.885 0.062 18.334);--color-selaras-red-300:oklch(0.808 0.114 19.571);--color-selaras-red-400:oklch(0.704 0.191 22.216);--color-selaras-red-500:oklch(0.637 0.237 25.331);--color-selaras-red-600:oklch(0.577 0.245 27.325);--color-selaras-red-700:oklch(0.505 0.213 27.518);--color-selaras-red-800:oklch(0.444 0.177 26.899);--color-selaras-red-900:oklch(0.396 0.141 25.723);--color-selaras-red-950:oklch(0.258 0.092 26.042);--color-selaras-yellow-50:oklch(0.987 0.026 102.212);--color-selaras-yellow-100:oklch(0.973 0.071 103.193);--color-selaras-yellow-200:oklch(0.945 0.129 101.54);--color-selaras-yellow-300:oklch(0.905 0.182 98.111);--color-selaras-yellow-400:oklch(0.852 0.199 91.936);--color-selaras-yellow-500:oklch(0.795 0.184 86.047);--color-selaras-yellow-600:oklch(0.681 0.162 75.834);--color-selaras-yellow-700:oklch(0.554 0.135 66.442);--color-selaras-yellow-800:oklch(0.476 0.114 61.907);--color-selaras-yellow-900:oklch(0.421 0.095 57.708);--color-selaras-yellow-950:oklch(0.286 0.066 53.813)}@layer theme{:root,[data-selaras-theme]{--_selaras-default-surface-canvas:#fff;--_selaras-default-surface-default:--theme(--color-selaras-gray-25);--_selaras-default-surface-elevated:--theme(--color-selaras-gray-50);--_selaras-default-surface-inverted:--theme(--color-selaras-gray-950);--_selaras-default-text-default:--theme(--color-selaras-gray-950);--_selaras-default-text-muted:--theme(--color-selaras-gray-600);--_selaras-default-text-inverted:--theme(--color-selaras-gray-50);--_selaras-default-border-default:--theme(--color-selaras-gray-200);--_selaras-default-border-muted:--theme(--color-selaras-gray-100);--_selaras-default-border-hover:--theme(--color-selaras-gray-300)}:root.dark,:root.dark [data-selaras-theme]:where(:not([data-selaras-mode]),[data-selaras-mode=root]),[data-selaras-theme]:where([data-selaras-mode=dark]){--_selaras-default-surface-canvas:#0c0c0d;--_selaras-default-surface-default:--theme(--color-selaras-gray-950);--_selaras-default-surface-elevated:--theme(--color-selaras-gray-900);--_selaras-default-surface-inverted:--theme(--color-selaras-gray-50);--_selaras-default-text-default:--theme(--color-selaras-gray-50);--_selaras-default-text-muted:--theme(--color-selaras-gray-400);--_selaras-default-text-inverted:--theme(--color-selaras-gray-950);--_selaras-default-border-default:--theme(--color-selaras-gray-800);--_selaras-default-border-muted:--theme(--color-selaras-gray-900);--_selaras-default-border-hover:--theme(--color-selaras-gray-700)}}
@@ -339,7 +339,7 @@ const messages = useMessages();
339
339
  const theme = useComponentTheme("select", selectTheme);
340
340
  const themeBindings = useThemeBindings();
341
341
  const effectiveColor = computed(() => resolveRegisteredColorRole(props.color ?? "primary", "primary"));
342
- const colorRoleMarker = computed(() => effectiveColor.value);
342
+ const colorRoleMarker = computed(() => selectInvalid.value ? "danger" : effectiveColor.value);
343
343
  const ui = computed(() => theme.value({ size: effectiveSize.value, color: effectiveColor.value, invalid: selectInvalid.value }));
344
344
  const nativeTriggerAttrs = useFallthroughAttrs((key) => !props.creatable && (isNativeInputA11yAttr(key) || !props.searchable && isNativeInputEvent(key)));
345
345
  const rootProps = useRootProps(() => ui.value.root, () => props.ui?.root, { exclude: (key) => isNativeInputA11yAttr(key) || isNativeInputEvent(key) || (props.creatable || props.searchable) && isNativeInputAttr(key) });
@@ -1 +1 @@
1
- @import "tw-animate-css";@source "./components";@source "./internal";@source "./theme";@source "./utils";@custom-variant dark (&:where(.dark, .dark *));@layer base{a:focus-visible{outline-offset:0}}@keyframes selaras-ripple{to{opacity:0;transform:scale(1)}}@keyframes selaras-accordion-down{0%{height:0}to{height:var(--reka-accordion-content-height)}}@keyframes selaras-accordion-up{0%{height:var(--reka-accordion-content-height)}to{height:0}}@keyframes selaras-collapsible-down{0%{height:0}to{height:var(--reka-collapsible-content-height)}}@keyframes selaras-collapsible-up{0%{height:var(--reka-collapsible-content-height)}to{height:0}}@keyframes selaras-skeleton-shimmer{0%{background-position:150% 0}to{background-position:-50% 0}}@keyframes selaras-progress-indeterminate{0%{transform:translateX(-100%)}to{transform:translateX(300%)}}@media (prefers-reduced-motion:reduce){*,:after,:before{animation-duration:.01ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-duration:.01ms!important}}.selaras-nav-elbow{position:relative}.selaras-nav-elbow:before{inset-inline-start:-16px;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;width:16px}.selaras-nav-elbow:after,.selaras-nav-elbow:before{background-color:var(--selaras-resolved-border-default);content:"";position:absolute;top:0}.selaras-nav-elbow:after{inset-inline-start:-15px;width:1.5px}.selaras-nav-elbow--content-navigation:before{height:40px;-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 40'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 14a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 40'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 14a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E")}.selaras-nav-elbow--content-navigation:after{bottom:-2px}.selaras-nav-elbow--content-navigation:last-child:after{bottom:auto;height:14px}.selaras-nav-elbow--navigation-menu:before{height:32px;-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 32'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 10a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 32'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 10a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E")}.selaras-nav-elbow--navigation-menu:after{bottom:-4px}.selaras-nav-elbow--navigation-menu:last-child:after{bottom:auto;height:10px}.selaras-nav-elbow--file-tree:before{height:28px;-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 28'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 8a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 28'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 8a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E")}.selaras-nav-elbow--file-tree:after{bottom:-2px}.selaras-nav-elbow--file-tree:last-child:after{bottom:auto;height:8px}@layer theme{:root,[data-selaras-theme]{--selaras-resolved-surface-default:var(--selaras-surface-default,var(--_selaras-default-surface-default));--selaras-resolved-surface-elevated:var(--selaras-surface-elevated,var(--_selaras-default-surface-elevated));--selaras-resolved-surface-inverted:var(--selaras-surface-inverted,var(--_selaras-default-surface-inverted));--selaras-resolved-text-default:var(--selaras-text-default,var(--_selaras-default-text-default));--selaras-resolved-text-muted:var(--selaras-text-muted,var(--_selaras-default-text-muted));--selaras-resolved-text-inverted:var(--selaras-text-inverted,var(--_selaras-default-text-inverted));--selaras-resolved-border-default:var(--selaras-border-default,var(--_selaras-default-border-default));--selaras-resolved-border-muted:var(--selaras-border-muted,var(--_selaras-default-border-muted));--selaras-resolved-border-hover:var(--selaras-border-hover,var(--_selaras-default-border-hover));--selaras-resolved-scrim:var(--selaras-scrim,rgba(0,0,0,.5));--selaras-resolved-radius-base:var(--selaras-radius-base,8px);--selaras-resolved-radius-sm:var(--selaras-radius-sm,calc(var(--selaras-resolved-radius-base)*0.75));--selaras-resolved-radius-md:var(--selaras-radius-md,var(--selaras-resolved-radius-base));--selaras-resolved-radius-lg:var(--selaras-radius-lg,calc(var(--selaras-resolved-radius-base)*2));--selaras-resolved-radius-full:var(--selaras-radius-full,9999px);--selaras-resolved-shadow-sm:var(--selaras-shadow-sm,0 1px 2px 0 rgba(0,0,0,.06));--selaras-resolved-shadow-md:var(--selaras-shadow-md,0 4px 16px -2px rgba(0,0,0,.12));--selaras-resolved-shadow-lg:var(--selaras-shadow-lg,0 12px 32px -4px rgba(0,0,0,.16));--selaras-resolved-z-modal-overlay:var(--selaras-z-modal-overlay,40);--selaras-resolved-z-modal:var(--selaras-z-modal,50);--selaras-resolved-z-dropdown:var(--selaras-z-dropdown,60);--selaras-resolved-z-tooltip:var(--selaras-z-tooltip,70);--selaras-resolved-z-toast:var(--selaras-z-toast,80)}:root.dark,:root.dark [data-selaras-theme]:where(:not([data-selaras-mode]),[data-selaras-mode=root]),[data-selaras-theme]:where([data-selaras-mode=dark]){--selaras-resolved-surface-default:var(--selaras-surface-default,var(--_selaras-default-surface-default));--selaras-resolved-surface-elevated:var(--selaras-surface-elevated,var(--_selaras-default-surface-elevated));--selaras-resolved-surface-inverted:var(--selaras-surface-inverted,var(--_selaras-default-surface-inverted));--selaras-resolved-text-default:var(--selaras-text-default,var(--_selaras-default-text-default));--selaras-resolved-text-muted:var(--selaras-text-muted,var(--_selaras-default-text-muted));--selaras-resolved-text-inverted:var(--selaras-text-inverted,var(--_selaras-default-text-inverted));--selaras-resolved-border-default:var(--selaras-border-default,var(--_selaras-default-border-default));--selaras-resolved-border-muted:var(--selaras-border-muted,var(--_selaras-default-border-muted));--selaras-resolved-border-hover:var(--selaras-border-hover,var(--_selaras-default-border-hover))}}
1
+ @import "tw-animate-css";@source "./components";@source "./internal";@source "./theme";@source "./utils";@custom-variant dark (&:where(.dark, .dark *));@layer base{a:focus-visible{outline-offset:0}}@keyframes selaras-ripple{to{opacity:0;transform:scale(1)}}@keyframes selaras-accordion-down{0%{height:0}to{height:var(--reka-accordion-content-height)}}@keyframes selaras-accordion-up{0%{height:var(--reka-accordion-content-height)}to{height:0}}@keyframes selaras-collapsible-down{0%{height:0}to{height:var(--reka-collapsible-content-height)}}@keyframes selaras-collapsible-up{0%{height:var(--reka-collapsible-content-height)}to{height:0}}@keyframes selaras-skeleton-shimmer{0%{background-position:150% 0}to{background-position:-50% 0}}@keyframes selaras-progress-indeterminate{0%{transform:translateX(-100%)}to{transform:translateX(300%)}}@media (prefers-reduced-motion:reduce){*,:after,:before{animation-duration:.01ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-duration:.01ms!important}}.selaras-nav-elbow{position:relative}.selaras-nav-elbow:before{inset-inline-start:-16px;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;width:16px}.selaras-nav-elbow:after,.selaras-nav-elbow:before{background-color:var(--selaras-resolved-border-default);content:"";position:absolute;top:0}.selaras-nav-elbow:after{inset-inline-start:-15px;width:1.5px}.selaras-nav-elbow--content-navigation:before{height:40px;-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 40'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 14a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 40'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 14a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E")}.selaras-nav-elbow--content-navigation:after{bottom:-2px}.selaras-nav-elbow--content-navigation:last-child:after{bottom:auto;height:14px}.selaras-nav-elbow--navigation-menu:before{height:32px;-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 32'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 10a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 32'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 10a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E")}.selaras-nav-elbow--navigation-menu:after{bottom:-4px}.selaras-nav-elbow--navigation-menu:last-child:after{bottom:auto;height:10px}.selaras-nav-elbow--file-tree:before{height:28px;-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 28'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 8a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 28'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M1 8a6 6 0 0 0 6 6h7'/%3E%3C/svg%3E")}.selaras-nav-elbow--file-tree:after{bottom:-2px}.selaras-nav-elbow--file-tree:last-child:after{bottom:auto;height:8px}@layer theme{:root,[data-selaras-theme]{--selaras-resolved-surface-canvas:var(--selaras-surface-canvas,var(--_selaras-default-surface-canvas));--selaras-resolved-surface-default:var(--selaras-surface-default,var(--_selaras-default-surface-default));--selaras-resolved-surface-elevated:var(--selaras-surface-elevated,var(--_selaras-default-surface-elevated));--selaras-resolved-surface-inverted:var(--selaras-surface-inverted,var(--_selaras-default-surface-inverted));--selaras-resolved-text-default:var(--selaras-text-default,var(--_selaras-default-text-default));--selaras-resolved-text-muted:var(--selaras-text-muted,var(--_selaras-default-text-muted));--selaras-resolved-text-inverted:var(--selaras-text-inverted,var(--_selaras-default-text-inverted));--selaras-resolved-border-default:var(--selaras-border-default,var(--_selaras-default-border-default));--selaras-resolved-border-muted:var(--selaras-border-muted,var(--_selaras-default-border-muted));--selaras-resolved-border-hover:var(--selaras-border-hover,var(--_selaras-default-border-hover));--selaras-resolved-scrim:var(--selaras-scrim,rgba(0,0,0,.5));--selaras-resolved-radius-base:var(--selaras-radius-base,8px);--selaras-resolved-radius-sm:var(--selaras-radius-sm,calc(var(--selaras-resolved-radius-base)*0.75));--selaras-resolved-radius-md:var(--selaras-radius-md,var(--selaras-resolved-radius-base));--selaras-resolved-radius-lg:var(--selaras-radius-lg,calc(var(--selaras-resolved-radius-base)*2));--selaras-resolved-radius-full:var(--selaras-radius-full,9999px);--selaras-resolved-shadow-sm:var(--selaras-shadow-sm,0 1px 2px 0 rgba(0,0,0,.06));--selaras-resolved-shadow-md:var(--selaras-shadow-md,0 4px 16px -2px rgba(0,0,0,.12));--selaras-resolved-shadow-lg:var(--selaras-shadow-lg,0 12px 32px -4px rgba(0,0,0,.16));--selaras-resolved-z-modal-overlay:var(--selaras-z-modal-overlay,40);--selaras-resolved-z-modal:var(--selaras-z-modal,50);--selaras-resolved-z-dropdown:var(--selaras-z-dropdown,60);--selaras-resolved-z-tooltip:var(--selaras-z-tooltip,70);--selaras-resolved-z-toast:var(--selaras-z-toast,80)}:root.dark,:root.dark [data-selaras-theme]:where(:not([data-selaras-mode]),[data-selaras-mode=root]),[data-selaras-theme]:where([data-selaras-mode=dark]){--selaras-resolved-surface-canvas:var(--selaras-surface-canvas,var(--_selaras-default-surface-canvas));--selaras-resolved-surface-default:var(--selaras-surface-default,var(--_selaras-default-surface-default));--selaras-resolved-surface-elevated:var(--selaras-surface-elevated,var(--_selaras-default-surface-elevated));--selaras-resolved-surface-inverted:var(--selaras-surface-inverted,var(--_selaras-default-surface-inverted));--selaras-resolved-text-default:var(--selaras-text-default,var(--_selaras-default-text-default));--selaras-resolved-text-muted:var(--selaras-text-muted,var(--_selaras-default-text-muted));--selaras-resolved-text-inverted:var(--selaras-text-inverted,var(--_selaras-default-text-inverted));--selaras-resolved-border-default:var(--selaras-border-default,var(--_selaras-default-border-default));--selaras-resolved-border-muted:var(--selaras-border-muted,var(--_selaras-default-border-muted));--selaras-resolved-border-hover:var(--selaras-border-hover,var(--_selaras-default-border-hover))}}
@@ -31,13 +31,13 @@ export const avatarTheme = tv({
31
31
  // (online, offline, ...) rarely match the avatar's own identity color, so
32
32
  // it gets its own variant rather than tracking the avatar's.
33
33
  statusColor: {
34
- primary: { status: "bg-[var(--selaras-resolved-color-primary-fill)]" },
35
- neutral: { status: "bg-[var(--selaras-resolved-text-muted)]" },
36
- secondary: { status: "bg-[var(--selaras-resolved-color-secondary-fill)]" },
37
- success: { status: "bg-[var(--selaras-resolved-color-success-fill)]" },
38
- danger: { status: "bg-[var(--selaras-resolved-color-danger-fill)]" },
39
- info: { status: "bg-[var(--selaras-resolved-color-info-fill)]" },
40
- warning: { status: "bg-[var(--selaras-resolved-color-warning-fill)]" }
34
+ primary: { status: "bg-[var(--selaras-resolved-color-primary-indicator)]" },
35
+ neutral: { status: "bg-[var(--selaras-resolved-color-neutral-indicator)]" },
36
+ secondary: { status: "bg-[var(--selaras-resolved-color-secondary-indicator)]" },
37
+ success: { status: "bg-[var(--selaras-resolved-color-success-indicator)]" },
38
+ danger: { status: "bg-[var(--selaras-resolved-color-danger-indicator)]" },
39
+ info: { status: "bg-[var(--selaras-resolved-color-info-indicator)]" },
40
+ warning: { status: "bg-[var(--selaras-resolved-color-warning-indicator)]" }
41
41
  },
42
42
  size: {
43
43
  sm: { base: "size-6", fallback: "text-[10px]", icon: "size-3", status: "size-1.5" },
@@ -9,8 +9,8 @@ export const badgeTheme = tv({
9
9
  leadingIcon: "shrink-0",
10
10
  label: "truncate",
11
11
  trailingIcon: "shrink-0",
12
- // Standalone dots use role text for surface contrast; inline dots use the pill foreground.
13
- dot: "shrink-0 rounded-full bg-[var(--_selaras-color-text)]"
12
+ // Standalone dots are unpaired graphics; inline dots use the pill foreground.
13
+ dot: "shrink-0 rounded-full bg-[var(--_selaras-color-indicator)]"
14
14
  },
15
15
  variants: {
16
16
  color: {
@@ -82,7 +82,7 @@ export const checkboxTheme = tv({
82
82
  // requested, not whichever variant happens to compose later. See
83
83
  // RadioGroup's own theme file, which already has this order right.
84
84
  invalid: {
85
- true: { box: "ring-[var(--_selaras-color-fill)] data-[state=checked]:ring-[var(--_selaras-color-fill)] data-[state=indeterminate]:ring-[var(--_selaras-color-fill)]" }
85
+ true: { box: "ring-[var(--_selaras-color-border)] data-[state=checked]:ring-[var(--_selaras-color-border)] data-[state=indeterminate]:ring-[var(--_selaras-color-border)]" }
86
86
  }
87
87
  },
88
88
  defaultVariants: {
@@ -59,7 +59,7 @@ export const datePickerTheme = tv({
59
59
  lg: { field: "h-11 px-3.5 text-base" }
60
60
  },
61
61
  invalid: {
62
- true: { field: "ring-[var(--_selaras-color-fill)] hover:ring-[var(--_selaras-color-fill)] focus-within:ring-[var(--_selaras-color-fill)]" }
62
+ true: { field: "ring-[var(--_selaras-color-border)] hover:ring-[var(--_selaras-color-border)] focus-within:ring-[var(--_selaras-color-focus)]" }
63
63
  },
64
64
  // Range mode's day cells butt up against each other with no horizontal
65
65
  // gap, so a highlighted run of days reads as one continuous connected
@@ -7,7 +7,7 @@ export const fileUploadTheme = tv({
7
7
  // instead of needing hand-rolled keydown handling. dragging (a
8
8
  // component-set data attribute, not a native one) recolors it
9
9
  // toward `color` - see the color variant below.
10
- dropzone: "flex w-full flex-col items-center justify-center gap-2 rounded-[var(--selaras-resolved-radius-md)] border-2 border-dashed border-[var(--selaras-resolved-border-default)] p-6 text-center transition-colors hover:border-[var(--selaras-resolved-border-hover)] hover:bg-[var(--selaras-resolved-surface-elevated)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--_selaras-color-focus)] data-[dragging]:border-[var(--_selaras-color-fill)] data-[dragging]:bg-[var(--_selaras-color-subtle)] disabled:opacity-50 disabled:pointer-events-none",
10
+ dropzone: "flex w-full flex-col items-center justify-center gap-2 rounded-[var(--selaras-resolved-radius-md)] border-2 border-dashed border-[var(--selaras-resolved-border-default)] p-6 text-center transition-colors hover:border-[var(--selaras-resolved-border-hover)] hover:bg-[var(--selaras-resolved-surface-elevated)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--_selaras-color-focus)] data-[dragging]:border-[var(--_selaras-color-border)] data-[dragging]:bg-[var(--_selaras-color-subtle)] disabled:opacity-50 disabled:pointer-events-none",
11
11
  icon: "text-[var(--_selaras-color-fill)]",
12
12
  label: "font-medium text-[var(--selaras-resolved-text-default)]",
13
13
  description: "text-[var(--selaras-resolved-text-muted)]",
@@ -54,7 +54,7 @@ export const fileUploadTheme = tv({
54
54
  // override win over color's - matches Input's own documented
55
55
  // reasoning for this order.
56
56
  invalid: {
57
- true: { dropzone: "border-[var(--_selaras-color-fill)] focus-visible:ring-[var(--_selaras-color-fill)]" }
57
+ true: { dropzone: "border-[var(--_selaras-color-border)] focus-visible:ring-[var(--_selaras-color-focus)]" }
58
58
  }
59
59
  },
60
60
  defaultVariants: {
@@ -27,7 +27,7 @@ export const iconTheme = tv({
27
27
  // role with no finite built-in branch, while leaving uncolored icons free
28
28
  // to inherit currentColor.
29
29
  colored: {
30
- true: { base: "text-[var(--_selaras-color-fill)]" }
30
+ true: { base: "text-[var(--_selaras-color-indicator)]" }
31
31
  }
32
32
  },
33
33
  compoundVariants: [
@@ -66,7 +66,7 @@ export const inputNumberTheme = tv({
66
66
  // focus-within:ring override win over color's - see input.ts for why
67
67
  // declaration order (not runtime call order) is what decides this.
68
68
  invalid: {
69
- true: { root: "ring-[var(--_selaras-color-fill)] hover:ring-[var(--_selaras-color-fill)] focus-within:ring-[var(--_selaras-color-fill)]" }
69
+ true: { root: "ring-[var(--_selaras-color-border)] hover:ring-[var(--_selaras-color-border)] focus-within:ring-[var(--_selaras-color-focus)]" }
70
70
  }
71
71
  },
72
72
  defaultVariants: {
@@ -54,7 +54,7 @@ export const inputTheme = tv({
54
54
  // Checkbox/Switch fix for why declaration order (not runtime call
55
55
  // order) is what decides this.
56
56
  invalid: {
57
- true: { base: "ring-[var(--_selaras-color-fill)] hover:ring-[var(--_selaras-color-fill)] focus:ring-[var(--_selaras-color-fill)]" }
57
+ true: { base: "ring-[var(--_selaras-color-border)] hover:ring-[var(--_selaras-color-border)] focus:ring-[var(--_selaras-color-focus)]" }
58
58
  }
59
59
  },
60
60
  compoundVariants: [
@@ -32,7 +32,7 @@ export const pinInputTheme = tv({
32
32
  // focus:ring override win over color's - matches Input's own
33
33
  // documented reasoning for this order.
34
34
  invalid: {
35
- true: { input: "ring-[var(--_selaras-color-fill)] hover:ring-[var(--_selaras-color-fill)] focus:ring-[var(--_selaras-color-fill)]" }
35
+ true: { input: "ring-[var(--_selaras-color-border)] hover:ring-[var(--_selaras-color-border)] focus:ring-[var(--_selaras-color-focus)]" }
36
36
  }
37
37
  },
38
38
  defaultVariants: {
@@ -3,7 +3,7 @@ export const progressTheme = tv({
3
3
  slots: {
4
4
  // Linear
5
5
  root: "relative w-full overflow-hidden rounded-full bg-[var(--selaras-resolved-surface-elevated)]",
6
- indicator: "h-full rounded-full bg-[var(--_selaras-color-fill)]",
6
+ indicator: "h-full rounded-full bg-[var(--_selaras-color-indicator)]",
7
7
  // Circular - a relative wrapper (for the centered label overlay) around
8
8
  // an SVG pair: a static background track circle plus an animated
9
9
  // foreground arc whose stroke-dasharray/dashoffset (computed in the
@@ -11,7 +11,7 @@ export const progressTheme = tv({
11
11
  circleRoot: "relative inline-flex items-center justify-center",
12
12
  circleWrapper: "",
13
13
  circleTrack: "stroke-[var(--selaras-resolved-surface-elevated)]",
14
- circleIndicator: "stroke-[var(--_selaras-color-fill)]",
14
+ circleIndicator: "stroke-[var(--_selaras-color-indicator)]",
15
15
  label: "absolute inset-0 flex items-center justify-center text-xs font-medium text-[var(--selaras-resolved-text-default)]"
16
16
  },
17
17
  variants: {
@@ -18,6 +18,8 @@ export declare const proseTheme: import("tailwind-variants").TVReturnType<{
18
18
  headingAnchor: string;
19
19
  preWrapper: string;
20
20
  preHeader: string;
21
+ preLabel: string;
22
+ preIcon: string;
21
23
  preFilename: string;
22
24
  preCopyButton: string;
23
25
  pre: string;
@@ -41,6 +43,8 @@ export declare const proseTheme: import("tailwind-variants").TVReturnType<{
41
43
  headingAnchor: string;
42
44
  preWrapper: string;
43
45
  preHeader: string;
46
+ preLabel: string;
47
+ preIcon: string;
44
48
  preFilename: string;
45
49
  preCopyButton: string;
46
50
  pre: string;
@@ -64,6 +68,8 @@ export declare const proseTheme: import("tailwind-variants").TVReturnType<{
64
68
  headingAnchor: string;
65
69
  preWrapper: string;
66
70
  preHeader: string;
71
+ preLabel: string;
72
+ preIcon: string;
67
73
  preFilename: string;
68
74
  preCopyButton: string;
69
75
  pre: string;
@@ -10,6 +10,8 @@ export const proseTheme = tv({
10
10
  headingAnchor: "no-underline hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--_selaras-color-focus)]",
11
11
  preWrapper: "overflow-hidden rounded-[var(--selaras-resolved-radius-md)] ring-1 ring-[var(--selaras-resolved-border-default)]",
12
12
  preHeader: "flex items-center justify-between gap-2 border-b border-[var(--selaras-resolved-border-default)] bg-[var(--selaras-resolved-surface-elevated)] px-3 py-1.5",
13
+ preLabel: "flex min-w-0 items-center gap-2",
14
+ preIcon: "size-4",
13
15
  preFilename: "font-mono text-xs text-[var(--selaras-resolved-text-muted)]",
14
16
  preCopyButton: "shrink-0",
15
17
  pre: "overflow-x-auto bg-[var(--selaras-resolved-surface-elevated)] p-4 font-mono text-sm leading-relaxed"
@@ -47,7 +47,7 @@ export const radioGroupTheme = tv({
47
47
  // rendered visibly jagged at normal (non-zoomed) browser scale; the
48
48
  // fractional width needs the arbitrary-value form since Tailwind's
49
49
  // named ring scale only has integer steps.
50
- item: "relative isolate flex shrink-0 items-center justify-center rounded-full ring-[1.5px] ring-inset ring-[var(--selaras-resolved-border-default)] transition-colors before:absolute before:-z-10 before:[transform:scale(0)] before:rounded-full before:bg-[var(--selaras-resolved-border-hover)] before:opacity-35 before:transition-transform before:duration-200 before:content-[''] hover:before:[transform:scale(1)] focus-visible:outline-none focus-visible:before:[transform:scale(1)] data-[state=checked]:ring-[var(--_selaras-color-fill)] data-[state=checked]:before:bg-[var(--_selaras-color-fill-hover)]",
50
+ item: "relative isolate flex shrink-0 items-center justify-center rounded-full ring-[1.5px] ring-inset ring-[var(--selaras-resolved-border-default)] transition-colors before:absolute before:-z-10 before:[transform:scale(0)] before:rounded-full before:bg-[var(--selaras-resolved-border-hover)] before:opacity-35 before:transition-transform before:duration-200 before:content-[''] hover:before:[transform:scale(1)] focus-visible:outline-none focus-visible:before:[transform:scale(1)] data-[state=checked]:ring-[var(--_selaras-color-indicator)] data-[state=checked]:before:bg-[var(--_selaras-color-fill-hover)]",
51
51
  // force-mount (see RadioGroup.vue) keeps this in the DOM for every
52
52
  // item regardless of checked state, so switching the selection scales
53
53
  // the old dot out and the new one in instead of an abrupt pop -
@@ -56,7 +56,7 @@ export const radioGroupTheme = tv({
56
56
  // detects them via computed animation-name), not plain CSS
57
57
  // transitions, so a transition-only version without force-mount would
58
58
  // just vanish instantly.
59
- indicator: "rounded-full bg-[var(--_selaras-color-fill)] [transform:scale(0)] transition-transform duration-200 data-[state=checked]:[transform:scale(1)]",
59
+ indicator: "rounded-full bg-[var(--_selaras-color-indicator)] [transform:scale(0)] transition-transform duration-200 data-[state=checked]:[transform:scale(1)]",
60
60
  label: "select-none text-[var(--selaras-resolved-text-default)]",
61
61
  description: "block select-none text-[var(--selaras-resolved-text-muted)]",
62
62
  // Only rendered when an item has a description (wrapping the label and
@@ -112,12 +112,12 @@ export const radioGroupTheme = tv({
112
112
  // otherwise win the ring color back whenever an already-invalid group
113
113
  // has something selected.
114
114
  invalid: {
115
- true: { item: "ring-[var(--_selaras-color-fill)] data-[state=checked]:ring-[var(--_selaras-color-fill)]" }
115
+ true: { item: "ring-[var(--_selaras-color-border)] data-[state=checked]:ring-[var(--_selaras-color-indicator)]" }
116
116
  }
117
117
  },
118
118
  compoundVariants: [
119
119
  // The card variant's own checked-state highlight, following `color`.
120
- { variant: "card", class: { itemWrapper: "has-[[data-state=checked]]:border-[var(--_selaras-color-fill)] has-[[data-state=checked]]:bg-[var(--_selaras-color-subtle)]" } }
120
+ { variant: "card", class: { itemWrapper: "has-[[data-state=checked]]:border-[var(--_selaras-color-border)] has-[[data-state=checked]]:bg-[var(--_selaras-color-subtle)]" } }
121
121
  ],
122
122
  defaultVariants: {
123
123
  size: "md",