ropav 0.0.2 → 0.0.3

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 (74) hide show
  1. package/README.md +32 -3
  2. package/dist/base.css +125 -88
  3. package/dist/button.css +259 -32
  4. package/dist/button.js +51 -19
  5. package/dist/button.js.map +1 -1
  6. package/dist/checkbox.css +125 -21
  7. package/dist/checkbox.js +77 -42
  8. package/dist/checkbox.js.map +1 -1
  9. package/dist/components/button/button.d.ts +2 -2
  10. package/dist/components/button/index.d.ts +1 -1
  11. package/dist/components/button/types.d.ts +8 -1
  12. package/dist/components/checkbox/index.d.ts +1 -1
  13. package/dist/components/checkbox/types.d.ts +8 -0
  14. package/dist/components/input/index.d.ts +1 -1
  15. package/dist/components/input/input.d.ts +5 -1
  16. package/dist/components/input/types.d.ts +5 -0
  17. package/dist/components/radio/index.d.ts +1 -1
  18. package/dist/components/radio/types.d.ts +12 -0
  19. package/dist/components/select/types.d.ts +3 -0
  20. package/dist/components/select/useSelect.d.ts +2 -0
  21. package/dist/components/switch/index.d.ts +1 -1
  22. package/dist/components/switch/types.d.ts +4 -0
  23. package/dist/components/textarea/index.d.ts +1 -1
  24. package/dist/components/textarea/types.d.ts +5 -0
  25. package/dist/components/textarea/useTextarea.d.ts +1 -0
  26. package/dist/index.d.ts +0 -2
  27. package/dist/index.js +2 -4
  28. package/dist/input.css +87 -21
  29. package/dist/input.js +66 -23
  30. package/dist/input.js.map +1 -1
  31. package/dist/radio.css +82 -18
  32. package/dist/radio.js +35 -8
  33. package/dist/radio.js.map +1 -1
  34. package/dist/select.css +104 -39
  35. package/dist/select.js +149 -87
  36. package/dist/select.js.map +1 -1
  37. package/dist/switch.css +75 -20
  38. package/dist/switch.js +8 -4
  39. package/dist/switch.js.map +1 -1
  40. package/dist/textarea.css +80 -20
  41. package/dist/textarea.js +33 -5
  42. package/dist/textarea.js.map +1 -1
  43. package/dist/useControlState.js +4 -0
  44. package/dist/useControlState.js.map +1 -1
  45. package/package.json +9 -9
  46. package/src/styles/_mixins.scss +18 -8
  47. package/src/styles/_tokens.scss +130 -99
  48. package/src/styles/_variables.scss +28 -28
  49. package/dist/components/_internal/icons/CheckIcon.d.ts +0 -18
  50. package/dist/components/_internal/icons/ChevronDownIcon.d.ts +0 -18
  51. package/dist/components/_internal/icons/MinusIcon.d.ts +0 -18
  52. package/dist/components/_internal/icons/index.d.ts +0 -3
  53. package/dist/components/_internal/optionList.d.ts +0 -9
  54. package/dist/components/tabs/index.d.ts +0 -5
  55. package/dist/components/tabs/index.js +0 -2
  56. package/dist/components/tabs/tab-panel.d.ts +0 -21
  57. package/dist/components/tabs/tabs-list.d.ts +0 -20
  58. package/dist/components/tabs/tabs-trigger.d.ts +0 -21
  59. package/dist/components/tabs/tabs.d.ts +0 -23
  60. package/dist/components/tabs/types.d.ts +0 -18
  61. package/dist/components/tabs/useTabs.d.ts +0 -19
  62. package/dist/components/tooltip/index.d.ts +0 -2
  63. package/dist/components/tooltip/index.js +0 -2
  64. package/dist/components/tooltip/tooltip.d.ts +0 -23
  65. package/dist/components/tooltip/types.d.ts +0 -5
  66. package/dist/components/tooltip/useTooltip.d.ts +0 -8
  67. package/dist/tabs.css +0 -45
  68. package/dist/tabs.js +0 -205
  69. package/dist/tabs.js.map +0 -1
  70. package/dist/tooltip.css +0 -78
  71. package/dist/tooltip.js +0 -112
  72. package/dist/tooltip.js.map +0 -1
  73. package/dist/useRequiredInject.js +0 -11
  74. package/dist/useRequiredInject.js.map +0 -1
package/dist/select.js CHANGED
@@ -1,30 +1,48 @@
1
1
  import './select.css';
2
2
  import { n as bem, t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper.js";
3
3
  import { t as useControlState } from "./useControlState.js";
4
- import { VaporTransition, child, computed, createComponent, createFor, createIf, createInvoker, createSelector, createSlot, createTemplateRefSetter, defineVaporComponent, delegateEvents, extend, next, nextTick, on, onBeforeUnmount, onMounted, ref, renderEffect, setAttr, setClass, setClassName, setInsertionState, setProp, setText, setValue, template, toDisplayString, txt, unref, useId, watch } from "vue";
5
- //#region src/components/_internal/icons/ChevronDownIcon.vue?vue&type=script&setup=true&vapor=true&lang.ts
6
- var t0$1 = template("<svg viewBox=\"0 0 16 16\"fill=none stroke=currentColor stroke-width=1.5><path d=\"M4 6l4 4 4-4\">", 3, 1);
7
- //#endregion
8
- //#region src/components/_internal/icons/ChevronDownIcon.vue
9
- var ChevronDownIcon_default = /* @__PURE__ */ defineVaporComponent({
10
- name: "ChevronDownIcon",
11
- __name: "ChevronDownIcon",
12
- setup(__props) {
13
- return t0$1();
14
- }
4
+ import { VaporTransition, child, computed, createComponent, createElementBlock, createElementVNode, createFor, createIf, createInvoker, createSelector, createSlot, createTemplateRefSetter, defineVaporComponent, delegateEvents, extend, markRaw, next, nextTick, on, onBeforeUnmount, onMounted, openBlock, ref, renderEffect, setAttr, setClass, setClassName, setInsertionState, setProp, setText, setValue, template, toDisplayString, txt, unref, useId, watch, withModifiers, withVaporModifiers } from "vue";
5
+ //#region ~icons/lucide/chevrons-up-down
6
+ var _hoisted_1$1 = {
7
+ viewBox: "0 0 24 24",
8
+ width: "1.2em",
9
+ height: "1.2em"
10
+ };
11
+ function render$1(_ctx, _cache) {
12
+ return openBlock(), createElementBlock("svg", _hoisted_1$1, [..._cache[0] || (_cache[0] = [createElementVNode("path", {
13
+ fill: "none",
14
+ stroke: "currentColor",
15
+ "stroke-linecap": "round",
16
+ "stroke-linejoin": "round",
17
+ "stroke-width": "2",
18
+ d: "m7 15l5 5l5-5M7 9l5-5l5 5"
19
+ }, null, -1)])]);
20
+ }
21
+ var chevrons_up_down_default = markRaw({
22
+ name: "lucide-chevrons-up-down",
23
+ render: render$1
15
24
  });
16
25
  //#endregion
17
- //#region src/components/_internal/optionList.ts
18
- function hasOptionListValue(value) {
19
- return value != null && value !== "";
20
- }
21
- function getOptionListDisplayLabel(options, value) {
22
- if (!hasOptionListValue(value)) return "";
23
- return options?.find((option) => option.value === value)?.label ?? "";
24
- }
25
- function getOptionListActiveDescendantId(baseId, focusedIndex) {
26
- return focusedIndex < 0 ? void 0 : `${baseId}-option-${focusedIndex}`;
26
+ //#region ~icons/lucide/x
27
+ var _hoisted_1 = {
28
+ viewBox: "0 0 24 24",
29
+ width: "1.2em",
30
+ height: "1.2em"
31
+ };
32
+ function render(_ctx, _cache) {
33
+ return openBlock(), createElementBlock("svg", _hoisted_1, [..._cache[0] || (_cache[0] = [createElementVNode("path", {
34
+ fill: "none",
35
+ stroke: "currentColor",
36
+ "stroke-linecap": "round",
37
+ "stroke-linejoin": "round",
38
+ "stroke-width": "2",
39
+ d: "M18 6L6 18M6 6l12 12"
40
+ }, null, -1)])]);
27
41
  }
42
+ var x_default = markRaw({
43
+ name: "lucide-x",
44
+ render
45
+ });
28
46
  //#endregion
29
47
  //#region src/composables/useClickOutside.ts
30
48
  function useClickOutside(target, active, callback) {
@@ -66,7 +84,15 @@ function useListNavigation(options) {
66
84
  localFocusedIndex.value = index;
67
85
  return;
68
86
  }
69
- const next = direction === 1 ? indexes.find((i) => i > index) : [...indexes].reverse().find((i) => i < index);
87
+ let next;
88
+ if (direction === 1) next = indexes.find((i) => i > index);
89
+ else for (let i = indexes.length - 1; i >= 0; i -= 1) {
90
+ const candidate = indexes[i];
91
+ if (candidate < index) {
92
+ next = candidate;
93
+ break;
94
+ }
95
+ }
70
96
  if (next !== void 0) localFocusedIndex.value = next;
71
97
  else if (loop) localFocusedIndex.value = direction === 1 ? indexes[0] : indexes[indexes.length - 1];
72
98
  }
@@ -86,7 +112,8 @@ function useListNavigation(options) {
86
112
  }
87
113
  function moveFocus(delta) {
88
114
  if (localFocusedIndex.value < 0) {
89
- delta === 1 ? focusFirst() : focusLast();
115
+ if (delta === 1) focusFirst();
116
+ else focusLast();
90
117
  return;
91
118
  }
92
119
  setNearest(localFocusedIndex.value + delta, delta);
@@ -102,6 +129,16 @@ function useListNavigation(options) {
102
129
  }
103
130
  //#endregion
104
131
  //#region src/components/select/useSelect.ts
132
+ function hasSelectValue(value) {
133
+ return value != null && value !== "";
134
+ }
135
+ function getSelectDisplayLabel(options, value) {
136
+ if (!hasSelectValue(value)) return "";
137
+ return options?.find((option) => option.value === value)?.label ?? "";
138
+ }
139
+ function getSelectActiveDescendantId(baseId, focusedIndex) {
140
+ return focusedIndex < 0 ? void 0 : `${baseId}-option-${focusedIndex}`;
141
+ }
105
142
  function useSelect(props, emitUpdate) {
106
143
  const selectRef = ref(null);
107
144
  const triggerRef = ref(null);
@@ -115,14 +152,16 @@ function useSelect(props, emitUpdate) {
115
152
  isSelected: (item) => item.value === props.modelValue
116
153
  });
117
154
  const focusedIndex = navigation.focusedIndex;
118
- const activeDescendantId = computed(() => getOptionListActiveDescendantId(selectId, focusedIndex.value));
155
+ const activeDescendantId = computed(() => getSelectActiveDescendantId(selectId, focusedIndex.value));
119
156
  const rootClass = computed(() => bem("rp-select", {
120
157
  open: isOpen.value,
158
+ [`radius-${props.radius}`]: Boolean(props.radius),
121
159
  disabled: control.disabled,
122
160
  invalid: control.invalid
123
161
  }));
124
- const hasValue = computed(() => hasOptionListValue(props.modelValue));
125
- const displayLabel = computed(() => getOptionListDisplayLabel(props.options, props.modelValue));
162
+ const hasValue = computed(() => hasSelectValue(props.modelValue));
163
+ const displayLabel = computed(() => getSelectDisplayLabel(props.options, props.modelValue));
164
+ const canClear = computed(() => Boolean(props.clearable && hasValue.value && !control.disabled));
126
165
  function focusTrigger() {
127
166
  nextTick(() => triggerRef.value?.focus());
128
167
  }
@@ -148,6 +187,12 @@ function useSelect(props, emitUpdate) {
148
187
  close();
149
188
  focusTrigger();
150
189
  }
190
+ function clearSelection() {
191
+ if (!canClear.value) return;
192
+ emitUpdate(null);
193
+ close();
194
+ focusTrigger();
195
+ }
151
196
  function onOptionMouseenter(option, index) {
152
197
  if (!option.disabled) focusedIndex.value = index;
153
198
  }
@@ -213,21 +258,24 @@ function useSelect(props, emitUpdate) {
213
258
  rootClass,
214
259
  hasValue,
215
260
  displayLabel,
261
+ canClear,
216
262
  toggle,
217
263
  selectOption,
264
+ clearSelection,
218
265
  onOptionMouseenter,
219
266
  onTriggerKeydown
220
267
  };
221
268
  }
222
269
  //#endregion
223
270
  //#region src/components/select/select.vue?vue&type=script&setup=true&vapor=true&lang.ts
224
- var t0 = template("<input data-v-692ef421 type=hidden>");
225
- var t1 = template("No options", 2);
226
- var t2 = template("<div data-v-692ef421 class=rp-select__empty>");
227
- var t3 = template("<div data-v-692ef421 role=option> ");
228
- var t4 = template("<div data-v-692ef421 class=rp-select__dropdown role=listbox>");
229
- var t5 = template("<div data-v-692ef421><div data-v-692ef421 class=rp-select__trigger role=combobox aria-haspopup=listbox><span data-v-692ef421> </span><span data-v-692ef421>", 1);
230
- delegateEvents("click", "keydown");
271
+ var t0 = template("<input data-v-9838513c type=hidden>");
272
+ var t1 = template("<button data-v-9838513c type=button class=rp-select__clear aria-label=\"Clear selection\"tabindex=-1></button>");
273
+ var t2 = template("No options", 2);
274
+ var t3 = template("<div data-v-9838513c class=rp-select__empty>");
275
+ var t4 = template("<div data-v-9838513c role=option> ");
276
+ var t5 = template("<div data-v-9838513c class=rp-select__dropdown role=listbox>");
277
+ var t6 = template("<div data-v-9838513c><div data-v-9838513c class=rp-select__trigger role=combobox aria-haspopup=listbox><span data-v-9838513c> </span><span data-v-9838513c class=rp-select__indicator><span data-v-9838513c class=rp-select__arrow aria-hidden=true>", 1);
278
+ delegateEvents("mousedown", "click", "keydown");
231
279
  //#endregion
232
280
  //#region src/components/select/select.vue
233
281
  var select_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineVaporComponent({
@@ -238,7 +286,12 @@ var select_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE_
238
286
  name: {},
239
287
  modelValue: {},
240
288
  options: { default: () => [] },
289
+ radius: {},
241
290
  placeholder: { default: "Select..." },
291
+ clearable: {
292
+ type: Boolean,
293
+ default: false
294
+ },
242
295
  disabled: {
243
296
  type: Boolean,
244
297
  default: void 0
@@ -259,16 +312,17 @@ var select_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE_
259
312
  setup(__props, { emit: __emit }) {
260
313
  const props = __props;
261
314
  const emit = __emit;
262
- const { selectRef, triggerRef, isOpen, selectId, listboxId, control, visibleOptions, focusedIndex, activeDescendantId, rootClass, hasValue, displayLabel, toggle, selectOption, onOptionMouseenter, onTriggerKeydown } = useSelect(props, (value) => {
315
+ const { selectRef, triggerRef, isOpen, selectId, listboxId, control, visibleOptions, focusedIndex, activeDescendantId, rootClass, hasValue, displayLabel, canClear, toggle, selectOption, clearSelection, onOptionMouseenter, onTriggerKeydown } = useSelect(props, (value) => {
263
316
  emit("update:modelValue", value);
264
317
  });
265
318
  const _setTemplateRef = createTemplateRefSetter();
266
- const n20 = t5();
267
- const n6 = child(n20, 1);
268
- const n3 = child(n6);
269
- const n5 = next(n3, 1);
270
- renderEffect(() => setClass(n20, unref(rootClass)));
271
- setInsertionState(n20, 0, 0);
319
+ const n25 = t6();
320
+ const n11 = child(n25, 1);
321
+ const n3 = child(n11);
322
+ const n10 = next(n3, 1);
323
+ const n9 = child(n10, 1);
324
+ renderEffect(() => setClass(n25, unref(rootClass)));
325
+ setInsertionState(n25, 0, 0);
272
326
  createIf(() => __props.name, () => {
273
327
  const n2 = t0();
274
328
  renderEffect(() => {
@@ -283,49 +337,57 @@ var select_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE_
283
337
  const _control = unref(control);
284
338
  const _isOpen = unref(isOpen);
285
339
  const _control_disabled = _control.disabled;
286
- setProp(n6, "id", _control.id);
287
- setAttr(n6, "aria-expanded", _isOpen);
288
- setAttr(n6, "aria-activedescendant", unref(activeDescendantId));
289
- setAttr(n6, "aria-controls", unref(listboxId));
290
- setAttr(n6, "aria-disabled", _control_disabled || void 0);
291
- setAttr(n6, "aria-invalid", _control.invalid || void 0);
292
- setAttr(n6, "aria-required", _control.required || void 0);
293
- setAttr(n6, "aria-label", __props.ariaLabel || void 0);
294
- setAttr(n6, "aria-labelledby", _control.ariaLabelledby);
295
- setAttr(n6, "aria-describedby", _control.ariaDescribedby);
296
- setAttr(n6, "data-state", _isOpen ? "open" : "closed");
297
- setAttr(n6, "data-disabled", _control_disabled || void 0);
298
- setProp(n6, "tabindex", _control_disabled ? -1 : 0);
340
+ setProp(n11, "id", _control.id);
341
+ setAttr(n11, "aria-expanded", _isOpen);
342
+ setAttr(n11, "aria-activedescendant", unref(activeDescendantId));
343
+ setAttr(n11, "aria-controls", unref(listboxId));
344
+ setAttr(n11, "aria-disabled", _control_disabled || void 0);
345
+ setAttr(n11, "aria-invalid", _control.invalid || void 0);
346
+ setAttr(n11, "aria-required", _control.required || void 0);
347
+ setAttr(n11, "aria-label", __props.ariaLabel || void 0);
348
+ setAttr(n11, "aria-labelledby", _control.ariaLabelledby);
349
+ setAttr(n11, "aria-describedby", _control.ariaDescribedby);
350
+ setAttr(n11, "data-state", _isOpen ? "open" : "closed");
351
+ setAttr(n11, "data-disabled", _control_disabled || void 0);
352
+ setProp(n11, "tabindex", _control_disabled ? -1 : 0);
299
353
  setClassName(n3, !unref(hasValue) ? 1 : 0, " rp-select__placeholder", "rp-select__value");
300
354
  setText(x3, toDisplayString(unref(displayLabel) || __props.placeholder));
301
- setClassName(n5, _isOpen ? 1 : 0, " rp-select__arrow--open", "rp-select__arrow");
302
355
  });
303
- setInsertionState(n5, null, 0);
304
- createComponent(unref(ChevronDownIcon_default));
305
- n6.$evtclick = createInvoker((e) => unref(toggle)(e));
306
- n6.$evtkeydown = createInvoker((e) => unref(onTriggerKeydown)(e));
307
- _setTemplateRef(n6, triggerRef, null, "triggerRef");
308
- setInsertionState(n20, null, 2);
356
+ setInsertionState(n10, 0, 0);
357
+ createIf(() => unref(canClear), () => {
358
+ const n7 = t1();
359
+ setInsertionState(n7, null, 0);
360
+ createComponent(unref(x_default));
361
+ n7.$evtmousedown = withVaporModifiers(() => {}, ["prevent"]);
362
+ on(n7, "click", withModifiers((e) => unref(clearSelection)(e), ["stop"]));
363
+ return n7;
364
+ });
365
+ setInsertionState(n9, null, 0);
366
+ createComponent(unref(chevrons_up_down_default));
367
+ n11.$evtclick = createInvoker((e) => unref(toggle)(e));
368
+ n11.$evtkeydown = createInvoker((e) => unref(onTriggerKeydown)(e));
369
+ _setTemplateRef(n11, triggerRef, null, "triggerRef");
370
+ setInsertionState(n25, null, 2);
309
371
  createComponent(VaporTransition, { name: "rp-select-dropdown" }, extend(() => {
310
372
  return createIf(() => unref(isOpen), () => {
311
- const n18 = t4();
312
- renderEffect(() => setProp(n18, "id", unref(listboxId)));
313
- setInsertionState(n18, null, 0);
373
+ const n23 = t5();
374
+ renderEffect(() => setProp(n23, "id", unref(listboxId)));
375
+ setInsertionState(n23, null, 0);
314
376
  createIf(() => unref(visibleOptions).length === 0, () => {
315
- const n14 = t2();
316
- setInsertionState(n14, null, 0);
377
+ const n19 = t3();
378
+ setInsertionState(n19, null, 0);
317
379
  createSlot("empty", null, () => {
318
- return t1();
380
+ return t2();
319
381
  }, 1);
320
- return n14;
382
+ return n19;
321
383
  });
322
- setInsertionState(n18, null, 1);
323
- const _selector15 = createSelector(() => __props.modelValue);
384
+ setInsertionState(n23, null, 1);
385
+ const _selector20 = createSelector(() => __props.modelValue);
324
386
  createFor(() => unref(visibleOptions), (_for_item0, _for_key0) => {
325
- const n17 = t3();
326
- const x17 = txt(n17);
327
- n17.$evtclick = createInvoker(() => unref(selectOption)(_for_item0.value));
328
- on(n17, "mouseenter", () => unref(onOptionMouseenter)(_for_item0.value, _for_key0.value));
387
+ const n22 = t4();
388
+ const x22 = txt(n22);
389
+ n22.$evtclick = createInvoker(() => unref(selectOption)(_for_item0.value));
390
+ on(n22, "mouseenter", () => unref(onOptionMouseenter)(_for_item0.value, _for_key0.value));
329
391
  let _index, _option, _modelValue, _option_disabled, _option_value;
330
392
  renderEffect(() => {
331
393
  _index = _for_key0.value;
@@ -333,29 +395,29 @@ var select_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE_
333
395
  _modelValue = __props.modelValue;
334
396
  _option_disabled = _option.disabled;
335
397
  _option_value = _option.value;
336
- setProp(n17, "id", `${unref(selectId)}-option-${_index}`);
337
- setAttr(n17, "aria-disabled", _option_disabled || void 0);
338
- setAttr(n17, "data-selected", _option_value === _modelValue || void 0);
339
- setAttr(n17, "data-disabled", _option_disabled || void 0);
340
- setClass(n17, ["rp-select__option", {
398
+ setProp(n22, "id", `${unref(selectId)}-option-${_index}`);
399
+ setAttr(n22, "aria-disabled", _option_disabled || void 0);
400
+ setAttr(n22, "data-selected", _option_value === _modelValue || void 0);
401
+ setAttr(n22, "data-disabled", _option_disabled || void 0);
402
+ setClass(n22, ["rp-select__option", {
341
403
  "rp-select__option--selected": _option_value === _modelValue,
342
404
  "rp-select__option--focused": _index === unref(focusedIndex),
343
405
  "rp-select__option--disabled": _option_disabled
344
406
  }]);
345
- setText(x17, toDisplayString(_option.label));
407
+ setText(x22, toDisplayString(_option.label));
346
408
  });
347
- _selector15(_option.value, () => {
348
- setAttr(n17, "aria-selected", _option.value === _modelValue);
409
+ _selector20(_option.value, () => {
410
+ setAttr(n22, "aria-selected", _option.value === _modelValue);
349
411
  });
350
- return n17;
351
- }, (option, index) => option.value, 8).onReset(_selector15.reset);
352
- return n18;
412
+ return n22;
413
+ }, (option, index) => option.value, 8).onReset(_selector20.reset);
414
+ return n23;
353
415
  }, null, 129);
354
416
  }, { _: 8 }));
355
- _setTemplateRef(n20, selectRef, null, "selectRef");
356
- return n20;
417
+ _setTemplateRef(n25, selectRef, null, "selectRef");
418
+ return n25;
357
419
  }
358
- }), [["__scopeId", "data-v-692ef421"]]);
420
+ }), [["__scopeId", "data-v-9838513c"]]);
359
421
  //#endregion
360
422
  export { select_default as t };
361
423
 
@@ -1 +1 @@
1
- {"version":3,"file":"select.js","names":[],"sources":["../src/components/_internal/icons/ChevronDownIcon.vue","../src/components/_internal/icons/ChevronDownIcon.vue","../src/components/_internal/optionList.ts","../src/composables/useClickOutside.ts","../src/composables/useListNavigation.ts","../src/components/select/useSelect.ts","../src/components/select/select.vue","../src/components/select/select.vue"],"sourcesContent":["<template>\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\n <path d=\"M4 6l4 4 4-4\" />\n </svg>\n</template>\n\n<script lang=\"ts\" setup vapor>\ndefineOptions({ name: 'ChevronDownIcon' });\n</script>\n","<template>\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\n <path d=\"M4 6l4 4 4-4\" />\n </svg>\n</template>\n\n<script lang=\"ts\" setup vapor>\ndefineOptions({ name: 'ChevronDownIcon' });\n</script>\n","export interface OptionListItem {\n label: string;\n value: string | number;\n disabled?: boolean;\n}\n\nexport type OptionListValue = string | number | null;\n\nexport function hasOptionListValue(value: OptionListValue) {\n return value != null && value !== '';\n}\n\nexport function getOptionListDisplayLabel<T extends OptionListItem>(\n options: T[] | undefined,\n value: OptionListValue,\n) {\n if (!hasOptionListValue(value)) return '';\n return options?.find((option) => option.value === value)?.label ?? '';\n}\n\nexport function getOptionListActiveDescendantId(baseId: string, focusedIndex: number) {\n return focusedIndex < 0 ? undefined : `${baseId}-option-${focusedIndex}`;\n}\n","import { watch, onMounted, onBeforeUnmount, type Ref } from 'vue';\n\nexport function useClickOutside(\n target: Ref<HTMLElement | null>,\n active: Ref<boolean>,\n callback: () => void,\n) {\n let isListening = false;\n let stopWatch: (() => void) | undefined;\n\n function handler(e: MouseEvent) {\n if (target.value && !target.value.contains(e.target as Node)) {\n callback();\n }\n }\n\n function setListening(value: boolean) {\n if (typeof document === 'undefined' || value === isListening) return;\n isListening = value;\n\n if (value) {\n document.addEventListener('click', handler, true);\n } else {\n document.removeEventListener('click', handler, true);\n }\n }\n\n onMounted(() => {\n stopWatch = watch(active, setListening, { immediate: true });\n });\n\n onBeforeUnmount(() => {\n stopWatch?.();\n setListening(false);\n });\n}\n","import { computed, ref } from 'vue';\n\nexport interface ListNavigationItem {\n disabled?: boolean;\n}\n\nexport interface UseListNavigationOptions<T extends ListNavigationItem> {\n items: () => T[];\n isSelected?: (item: T) => boolean;\n loop?: boolean;\n}\n\nexport function useListNavigation<T extends ListNavigationItem>(\n options: UseListNavigationOptions<T>,\n) {\n const localFocusedIndex = ref(-1);\n const loop = options.loop ?? true;\n\n const enabledIndexes = computed(() =>\n options.items()\n .map((item, index) => item.disabled ? -1 : index)\n .filter((index) => index >= 0),\n );\n\n function resetFocus() {\n localFocusedIndex.value = -1;\n }\n\n function setNearest(index: number, direction: 1 | -1) {\n const indexes = enabledIndexes.value;\n if (indexes.length === 0) {\n resetFocus();\n return;\n }\n\n if (options.items()[index] && !options.items()[index]?.disabled) {\n localFocusedIndex.value = index;\n return;\n }\n\n const next = direction === 1\n ? indexes.find((i) => i > index)\n : [...indexes].reverse().find((i) => i < index);\n\n if (next !== undefined) {\n localFocusedIndex.value = next;\n } else if (loop) {\n localFocusedIndex.value = direction === 1 ? indexes[0]! : indexes[indexes.length - 1]!;\n }\n }\n\n function focusSelected() {\n const items = options.items();\n const selectedIndex = options.isSelected\n ? items.findIndex((item) => options.isSelected!(item) && !item.disabled)\n : -1;\n if (selectedIndex >= 0) {\n localFocusedIndex.value = selectedIndex;\n } else {\n focusFirst();\n }\n }\n\n function focusFirst() {\n const first = enabledIndexes.value[0];\n localFocusedIndex.value = first ?? -1;\n }\n\n function focusLast() {\n const indexes = enabledIndexes.value;\n localFocusedIndex.value = indexes[indexes.length - 1] ?? -1;\n }\n\n function moveFocus(delta: 1 | -1) {\n if (localFocusedIndex.value < 0) {\n delta === 1 ? focusFirst() : focusLast();\n return;\n }\n setNearest(localFocusedIndex.value + delta, delta);\n }\n\n return {\n focusedIndex: localFocusedIndex,\n resetFocus,\n focusSelected,\n focusFirst,\n focusLast,\n moveFocus,\n };\n}\n","import { computed, nextTick, ref, useId } from 'vue';\nimport {\n getOptionListActiveDescendantId,\n getOptionListDisplayLabel,\n hasOptionListValue,\n} from '@/components/_internal/optionList';\nimport { useClickOutside } from '@/composables/useClickOutside';\nimport { useControlState } from '@/composables/useControlState';\nimport { useListNavigation } from '@/composables/useListNavigation';\nimport { bem } from '@/utils/bem';\nimport type { SelectOption, SelectProps } from './types';\n\ntype SelectValue = string | number | null;\n\nexport function useSelect(\n props: Readonly<SelectProps>,\n emitUpdate: (value: SelectValue) => void,\n) {\n const selectRef = ref<HTMLElement | null>(null);\n const triggerRef = ref<HTMLElement | null>(null);\n const isOpen = ref(false);\n\n const selectId = useId();\n const listboxId = `${selectId}-listbox`;\n\n const control = useControlState(props);\n const visibleOptions = computed(() => props.options ?? []);\n\n const navigation = useListNavigation<SelectOption>({\n items: () => visibleOptions.value,\n isSelected: (item) => item.value === props.modelValue,\n });\n\n const focusedIndex = navigation.focusedIndex;\n const activeDescendantId = computed(() =>\n getOptionListActiveDescendantId(selectId, focusedIndex.value),\n );\n\n const rootClass = computed(() =>\n bem('rp-select', {\n open: isOpen.value,\n disabled: control.disabled,\n invalid: control.invalid,\n }),\n );\n\n const hasValue = computed(() => hasOptionListValue(props.modelValue));\n const displayLabel = computed(() => getOptionListDisplayLabel(props.options, props.modelValue));\n\n function focusTrigger() {\n nextTick(() => triggerRef.value?.focus());\n }\n\n function open() {\n if (control.disabled || isOpen.value) return;\n isOpen.value = true;\n navigation.focusSelected();\n }\n\n function close() {\n isOpen.value = false;\n navigation.resetFocus();\n }\n\n function toggle() {\n if (control.disabled) return;\n if (isOpen.value) {\n close();\n focusTrigger();\n } else {\n open();\n }\n }\n\n function selectOption(option: SelectOption) {\n if (option.disabled) return;\n emitUpdate(option.value);\n close();\n focusTrigger();\n }\n\n function onOptionMouseenter(option: SelectOption, index: number) {\n if (!option.disabled) focusedIndex.value = index;\n }\n\n function selectFocusedOption() {\n if (focusedIndex.value < 0 || focusedIndex.value >= visibleOptions.value.length) return;\n selectOption(visibleOptions.value[focusedIndex.value]!);\n }\n\n function onTriggerKeydown(e: KeyboardEvent) {\n if (control.disabled) return;\n\n switch (e.key) {\n case 'Enter':\n e.preventDefault();\n if (!isOpen.value) open();\n else selectFocusedOption();\n break;\n case ' ':\n e.preventDefault();\n if (!isOpen.value) open();\n else selectFocusedOption();\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (!isOpen.value) open();\n else navigation.moveFocus(1);\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (!isOpen.value) {\n open();\n navigation.focusLast();\n } else {\n navigation.moveFocus(-1);\n }\n break;\n case 'Home':\n if (isOpen.value) {\n e.preventDefault();\n navigation.focusFirst();\n }\n break;\n case 'End':\n if (isOpen.value) {\n e.preventDefault();\n navigation.focusLast();\n }\n break;\n case 'Escape':\n e.preventDefault();\n close();\n focusTrigger();\n break;\n }\n }\n\n useClickOutside(selectRef, isOpen, close);\n\n return {\n selectRef,\n triggerRef,\n isOpen,\n selectId,\n listboxId,\n control,\n visibleOptions,\n focusedIndex,\n activeDescendantId,\n rootClass,\n hasValue,\n displayLabel,\n toggle,\n selectOption,\n onOptionMouseenter,\n onTriggerKeydown,\n };\n}\n","<template>\n <div :class=\"rootClass\" ref=\"selectRef\">\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"modelValue ?? ''\" :disabled=\"control.disabled || undefined\" />\n <div\n :id=\"control.id\"\n ref=\"triggerRef\"\n class=\"rp-select__trigger\"\n role=\"combobox\"\n :aria-expanded=\"isOpen\"\n aria-haspopup=\"listbox\"\n :aria-activedescendant=\"activeDescendantId\"\n :aria-controls=\"listboxId\"\n :aria-disabled=\"control.disabled || undefined\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n :data-disabled=\"control.disabled || undefined\"\n :tabindex=\"control.disabled ? -1 : 0\"\n @click=\"toggle\"\n @keydown=\"onTriggerKeydown\"\n >\n <span class=\"rp-select__value\" :class=\"{ 'rp-select__placeholder': !hasValue }\">\n {{ displayLabel || placeholder }}\n </span>\n\n <span class=\"rp-select__arrow\" :class=\"{ 'rp-select__arrow--open': isOpen }\">\n <ChevronDownIcon />\n </span>\n </div>\n\n <Transition name=\"rp-select-dropdown\">\n <div v-if=\"isOpen\" class=\"rp-select__dropdown\" role=\"listbox\" :id=\"listboxId\">\n <div\n v-if=\"visibleOptions.length === 0\"\n class=\"rp-select__empty\"\n >\n <slot name=\"empty\">No options</slot>\n </div>\n <div\n v-for=\"(option, index) in visibleOptions\"\n :key=\"option.value\"\n role=\"option\"\n :id=\"`${selectId}-option-${index}`\"\n :aria-selected=\"option.value === modelValue\"\n :aria-disabled=\"option.disabled || undefined\"\n :data-selected=\"option.value === modelValue || undefined\"\n :data-disabled=\"option.disabled || undefined\"\n :class=\"[\n 'rp-select__option',\n {\n 'rp-select__option--selected': option.value === modelValue,\n 'rp-select__option--focused': index === focusedIndex,\n 'rp-select__option--disabled': option.disabled,\n },\n ]\"\n @click=\"selectOption(option)\"\n @mouseenter=\"onOptionMouseenter(option, index)\"\n >\n {{ option.label }}\n </div>\n </div>\n </Transition>\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { ChevronDownIcon } from '@/components/_internal/icons';\nimport { useSelect } from './useSelect';\nimport type { SelectProps } from './types';\n\ndefineOptions({ name: 'RpSelect' });\n\nconst props = withDefaults(defineProps<SelectProps>(), {\n options: () => [],\n placeholder: 'Select...',\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number | null];\n}>();\n\nconst {\n selectRef,\n triggerRef,\n isOpen,\n selectId,\n listboxId,\n control,\n visibleOptions,\n focusedIndex,\n activeDescendantId,\n rootClass,\n hasValue,\n displayLabel,\n toggle,\n selectOption,\n onOptionMouseenter,\n onTriggerKeydown,\n} = useSelect(props, (value) => {\n emit('update:modelValue', value);\n});\n\nvoid selectRef;\nvoid triggerRef;\n</script>\n\n<style src=\"./select.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div :class=\"rootClass\" ref=\"selectRef\">\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"modelValue ?? ''\" :disabled=\"control.disabled || undefined\" />\n <div\n :id=\"control.id\"\n ref=\"triggerRef\"\n class=\"rp-select__trigger\"\n role=\"combobox\"\n :aria-expanded=\"isOpen\"\n aria-haspopup=\"listbox\"\n :aria-activedescendant=\"activeDescendantId\"\n :aria-controls=\"listboxId\"\n :aria-disabled=\"control.disabled || undefined\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n :data-disabled=\"control.disabled || undefined\"\n :tabindex=\"control.disabled ? -1 : 0\"\n @click=\"toggle\"\n @keydown=\"onTriggerKeydown\"\n >\n <span class=\"rp-select__value\" :class=\"{ 'rp-select__placeholder': !hasValue }\">\n {{ displayLabel || placeholder }}\n </span>\n\n <span class=\"rp-select__arrow\" :class=\"{ 'rp-select__arrow--open': isOpen }\">\n <ChevronDownIcon />\n </span>\n </div>\n\n <Transition name=\"rp-select-dropdown\">\n <div v-if=\"isOpen\" class=\"rp-select__dropdown\" role=\"listbox\" :id=\"listboxId\">\n <div\n v-if=\"visibleOptions.length === 0\"\n class=\"rp-select__empty\"\n >\n <slot name=\"empty\">No options</slot>\n </div>\n <div\n v-for=\"(option, index) in visibleOptions\"\n :key=\"option.value\"\n role=\"option\"\n :id=\"`${selectId}-option-${index}`\"\n :aria-selected=\"option.value === modelValue\"\n :aria-disabled=\"option.disabled || undefined\"\n :data-selected=\"option.value === modelValue || undefined\"\n :data-disabled=\"option.disabled || undefined\"\n :class=\"[\n 'rp-select__option',\n {\n 'rp-select__option--selected': option.value === modelValue,\n 'rp-select__option--focused': index === focusedIndex,\n 'rp-select__option--disabled': option.disabled,\n },\n ]\"\n @click=\"selectOption(option)\"\n @mouseenter=\"onOptionMouseenter(option, index)\"\n >\n {{ option.label }}\n </div>\n </div>\n </Transition>\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { ChevronDownIcon } from '@/components/_internal/icons';\nimport { useSelect } from './useSelect';\nimport type { SelectProps } from './types';\n\ndefineOptions({ name: 'RpSelect' });\n\nconst props = withDefaults(defineProps<SelectProps>(), {\n options: () => [],\n placeholder: 'Select...',\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number | null];\n}>();\n\nconst {\n selectRef,\n triggerRef,\n isOpen,\n selectId,\n listboxId,\n control,\n visibleOptions,\n focusedIndex,\n activeDescendantId,\n rootClass,\n hasValue,\n displayLabel,\n toggle,\n selectOption,\n onOptionMouseenter,\n onTriggerKeydown,\n} = useSelect(props, (value) => {\n emit('update:modelValue', value);\n});\n\nvoid selectRef;\nvoid triggerRef;\n</script>\n\n<style src=\"./select.scss\" lang=\"scss\" scoped></style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"select.js","names":[],"sources":["../src/composables/useClickOutside.ts","../src/composables/useListNavigation.ts","../src/components/select/useSelect.ts","../src/components/select/select.vue","../src/components/select/select.vue"],"sourcesContent":["import { watch, onMounted, onBeforeUnmount, type Ref } from 'vue';\n\nexport function useClickOutside(\n target: Ref<HTMLElement | null>,\n active: Ref<boolean>,\n callback: () => void,\n) {\n let isListening = false;\n let stopWatch: (() => void) | undefined;\n\n function handler(e: MouseEvent) {\n if (target.value && !target.value.contains(e.target as Node)) {\n callback();\n }\n }\n\n function setListening(value: boolean) {\n if (typeof document === 'undefined' || value === isListening) return;\n isListening = value;\n\n if (value) {\n document.addEventListener('click', handler, true);\n } else {\n document.removeEventListener('click', handler, true);\n }\n }\n\n onMounted(() => {\n stopWatch = watch(active, setListening, { immediate: true });\n });\n\n onBeforeUnmount(() => {\n stopWatch?.();\n setListening(false);\n });\n}\n","import { computed, ref } from 'vue';\n\nexport interface ListNavigationItem {\n disabled?: boolean;\n}\n\nexport interface UseListNavigationOptions<T extends ListNavigationItem> {\n items: () => T[];\n isSelected?: (item: T) => boolean;\n loop?: boolean;\n}\n\nexport function useListNavigation<T extends ListNavigationItem>(\n options: UseListNavigationOptions<T>,\n) {\n const localFocusedIndex = ref(-1);\n const loop = options.loop ?? true;\n\n const enabledIndexes = computed(() =>\n options\n .items()\n .map((item, index) => (item.disabled ? -1 : index))\n .filter((index) => index >= 0),\n );\n\n function resetFocus() {\n localFocusedIndex.value = -1;\n }\n\n function setNearest(index: number, direction: 1 | -1) {\n const indexes = enabledIndexes.value;\n if (indexes.length === 0) {\n resetFocus();\n return;\n }\n\n if (options.items()[index] && !options.items()[index]?.disabled) {\n localFocusedIndex.value = index;\n return;\n }\n\n let next: number | undefined;\n if (direction === 1) {\n next = indexes.find((i) => i > index);\n } else {\n for (let i = indexes.length - 1; i >= 0; i -= 1) {\n const candidate = indexes[i]!;\n if (candidate < index) {\n next = candidate;\n break;\n }\n }\n }\n\n if (next !== undefined) {\n localFocusedIndex.value = next;\n } else if (loop) {\n localFocusedIndex.value = direction === 1 ? indexes[0]! : indexes[indexes.length - 1]!;\n }\n }\n\n function focusSelected() {\n const items = options.items();\n const selectedIndex = options.isSelected\n ? items.findIndex((item) => options.isSelected!(item) && !item.disabled)\n : -1;\n if (selectedIndex >= 0) {\n localFocusedIndex.value = selectedIndex;\n } else {\n focusFirst();\n }\n }\n\n function focusFirst() {\n const first = enabledIndexes.value[0];\n localFocusedIndex.value = first ?? -1;\n }\n\n function focusLast() {\n const indexes = enabledIndexes.value;\n localFocusedIndex.value = indexes[indexes.length - 1] ?? -1;\n }\n\n function moveFocus(delta: 1 | -1) {\n if (localFocusedIndex.value < 0) {\n if (delta === 1) {\n focusFirst();\n } else {\n focusLast();\n }\n return;\n }\n setNearest(localFocusedIndex.value + delta, delta);\n }\n\n return {\n focusedIndex: localFocusedIndex,\n resetFocus,\n focusSelected,\n focusFirst,\n focusLast,\n moveFocus,\n };\n}\n","import { computed, nextTick, ref, useId } from 'vue';\nimport { useClickOutside } from '@/composables/useClickOutside';\nimport { useControlState } from '@/composables/useControlState';\nimport { useListNavigation } from '@/composables/useListNavigation';\nimport { bem } from '@/utils/bem';\nimport type { SelectOption, SelectProps } from './types';\n\ntype SelectValue = string | number | null;\n\nfunction hasSelectValue(value: SelectValue) {\n return value != null && value !== '';\n}\n\nfunction getSelectDisplayLabel(options: SelectOption[] | undefined, value: SelectValue) {\n if (!hasSelectValue(value)) return '';\n return options?.find((option) => option.value === value)?.label ?? '';\n}\n\nfunction getSelectActiveDescendantId(baseId: string, focusedIndex: number) {\n return focusedIndex < 0 ? undefined : `${baseId}-option-${focusedIndex}`;\n}\n\nexport function useSelect(props: Readonly<SelectProps>, emitUpdate: (value: SelectValue) => void) {\n const selectRef = ref<HTMLElement | null>(null);\n const triggerRef = ref<HTMLElement | null>(null);\n const isOpen = ref(false);\n\n const selectId = useId();\n const listboxId = `${selectId}-listbox`;\n\n const control = useControlState(props);\n const visibleOptions = computed(() => props.options ?? []);\n\n const navigation = useListNavigation<SelectOption>({\n items: () => visibleOptions.value,\n isSelected: (item) => item.value === props.modelValue,\n });\n\n const focusedIndex = navigation.focusedIndex;\n const activeDescendantId = computed(() =>\n getSelectActiveDescendantId(selectId, focusedIndex.value),\n );\n\n const rootClass = computed(() =>\n bem('rp-select', {\n open: isOpen.value,\n [`radius-${props.radius}`]: Boolean(props.radius),\n disabled: control.disabled,\n invalid: control.invalid,\n }),\n );\n\n const hasValue = computed(() => hasSelectValue(props.modelValue));\n const displayLabel = computed(() => getSelectDisplayLabel(props.options, props.modelValue));\n const canClear = computed(() =>\n Boolean(props.clearable && hasValue.value && !control.disabled),\n );\n\n function focusTrigger() {\n nextTick(() => triggerRef.value?.focus());\n }\n\n function open() {\n if (control.disabled || isOpen.value) return;\n isOpen.value = true;\n navigation.focusSelected();\n }\n\n function close() {\n isOpen.value = false;\n navigation.resetFocus();\n }\n\n function toggle() {\n if (control.disabled) return;\n if (isOpen.value) {\n close();\n focusTrigger();\n } else {\n open();\n }\n }\n\n function selectOption(option: SelectOption) {\n if (option.disabled) return;\n emitUpdate(option.value);\n close();\n focusTrigger();\n }\n\n function clearSelection() {\n if (!canClear.value) return;\n emitUpdate(null);\n close();\n focusTrigger();\n }\n\n function onOptionMouseenter(option: SelectOption, index: number) {\n if (!option.disabled) focusedIndex.value = index;\n }\n\n function selectFocusedOption() {\n if (focusedIndex.value < 0 || focusedIndex.value >= visibleOptions.value.length) return;\n selectOption(visibleOptions.value[focusedIndex.value]!);\n }\n\n function onTriggerKeydown(e: KeyboardEvent) {\n if (control.disabled) return;\n\n switch (e.key) {\n case 'Enter':\n e.preventDefault();\n if (!isOpen.value) open();\n else selectFocusedOption();\n break;\n case ' ':\n e.preventDefault();\n if (!isOpen.value) open();\n else selectFocusedOption();\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (!isOpen.value) open();\n else navigation.moveFocus(1);\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (!isOpen.value) {\n open();\n navigation.focusLast();\n } else {\n navigation.moveFocus(-1);\n }\n break;\n case 'Home':\n if (isOpen.value) {\n e.preventDefault();\n navigation.focusFirst();\n }\n break;\n case 'End':\n if (isOpen.value) {\n e.preventDefault();\n navigation.focusLast();\n }\n break;\n case 'Escape':\n e.preventDefault();\n close();\n focusTrigger();\n break;\n }\n }\n\n useClickOutside(selectRef, isOpen, close);\n\n return {\n selectRef,\n triggerRef,\n isOpen,\n selectId,\n listboxId,\n control,\n visibleOptions,\n focusedIndex,\n activeDescendantId,\n rootClass,\n hasValue,\n displayLabel,\n canClear,\n toggle,\n selectOption,\n clearSelection,\n onOptionMouseenter,\n onTriggerKeydown,\n };\n}\n","<template>\n <div :class=\"rootClass\" ref=\"selectRef\">\n <input\n v-if=\"name\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"modelValue ?? ''\"\n :disabled=\"control.disabled || undefined\"\n />\n <div\n :id=\"control.id\"\n ref=\"triggerRef\"\n class=\"rp-select__trigger\"\n role=\"combobox\"\n :aria-expanded=\"isOpen\"\n aria-haspopup=\"listbox\"\n :aria-activedescendant=\"activeDescendantId\"\n :aria-controls=\"listboxId\"\n :aria-disabled=\"control.disabled || undefined\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n :data-disabled=\"control.disabled || undefined\"\n :tabindex=\"control.disabled ? -1 : 0\"\n @click=\"toggle\"\n @keydown=\"onTriggerKeydown\"\n >\n <span class=\"rp-select__value\" :class=\"{ 'rp-select__placeholder': !hasValue }\">\n {{ displayLabel || placeholder }}\n </span>\n\n <span class=\"rp-select__indicator\">\n <button\n v-if=\"canClear\"\n type=\"button\"\n class=\"rp-select__clear\"\n aria-label=\"Clear selection\"\n tabindex=\"-1\"\n @mousedown.prevent\n @click.stop=\"clearSelection\"\n >\n <XIcon />\n </button>\n <span class=\"rp-select__arrow\" aria-hidden=\"true\">\n <ChevronsUpDownIcon />\n </span>\n </span>\n </div>\n\n <Transition name=\"rp-select-dropdown\">\n <div v-if=\"isOpen\" class=\"rp-select__dropdown\" role=\"listbox\" :id=\"listboxId\">\n <div v-if=\"visibleOptions.length === 0\" class=\"rp-select__empty\">\n <slot name=\"empty\">No options</slot>\n </div>\n <div\n v-for=\"(option, index) in visibleOptions\"\n :key=\"option.value\"\n role=\"option\"\n :id=\"`${selectId}-option-${index}`\"\n :aria-selected=\"option.value === modelValue\"\n :aria-disabled=\"option.disabled || undefined\"\n :data-selected=\"option.value === modelValue || undefined\"\n :data-disabled=\"option.disabled || undefined\"\n :class=\"[\n 'rp-select__option',\n {\n 'rp-select__option--selected': option.value === modelValue,\n 'rp-select__option--focused': index === focusedIndex,\n 'rp-select__option--disabled': option.disabled,\n },\n ]\"\n @click=\"selectOption(option)\"\n @mouseenter=\"onOptionMouseenter(option, index)\"\n >\n {{ option.label }}\n </div>\n </div>\n </Transition>\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport ChevronsUpDownIcon from '~icons/lucide/chevrons-up-down';\nimport XIcon from '~icons/lucide/x';\nimport { useSelect } from './useSelect';\nimport type { SelectProps } from './types';\n\ndefineOptions({ name: 'RpSelect' });\n\nconst props = withDefaults(defineProps<SelectProps>(), {\n options: () => [],\n placeholder: 'Select...',\n clearable: false,\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number | null];\n}>();\n\nconst {\n selectRef,\n triggerRef,\n isOpen,\n selectId,\n listboxId,\n control,\n visibleOptions,\n focusedIndex,\n activeDescendantId,\n rootClass,\n hasValue,\n displayLabel,\n canClear,\n toggle,\n selectOption,\n clearSelection,\n onOptionMouseenter,\n onTriggerKeydown,\n} = useSelect(props, (value) => {\n emit('update:modelValue', value);\n});\n\nvoid selectRef;\nvoid triggerRef;\n</script>\n\n<style src=\"./select.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div :class=\"rootClass\" ref=\"selectRef\">\n <input\n v-if=\"name\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"modelValue ?? ''\"\n :disabled=\"control.disabled || undefined\"\n />\n <div\n :id=\"control.id\"\n ref=\"triggerRef\"\n class=\"rp-select__trigger\"\n role=\"combobox\"\n :aria-expanded=\"isOpen\"\n aria-haspopup=\"listbox\"\n :aria-activedescendant=\"activeDescendantId\"\n :aria-controls=\"listboxId\"\n :aria-disabled=\"control.disabled || undefined\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n :data-disabled=\"control.disabled || undefined\"\n :tabindex=\"control.disabled ? -1 : 0\"\n @click=\"toggle\"\n @keydown=\"onTriggerKeydown\"\n >\n <span class=\"rp-select__value\" :class=\"{ 'rp-select__placeholder': !hasValue }\">\n {{ displayLabel || placeholder }}\n </span>\n\n <span class=\"rp-select__indicator\">\n <button\n v-if=\"canClear\"\n type=\"button\"\n class=\"rp-select__clear\"\n aria-label=\"Clear selection\"\n tabindex=\"-1\"\n @mousedown.prevent\n @click.stop=\"clearSelection\"\n >\n <XIcon />\n </button>\n <span class=\"rp-select__arrow\" aria-hidden=\"true\">\n <ChevronsUpDownIcon />\n </span>\n </span>\n </div>\n\n <Transition name=\"rp-select-dropdown\">\n <div v-if=\"isOpen\" class=\"rp-select__dropdown\" role=\"listbox\" :id=\"listboxId\">\n <div v-if=\"visibleOptions.length === 0\" class=\"rp-select__empty\">\n <slot name=\"empty\">No options</slot>\n </div>\n <div\n v-for=\"(option, index) in visibleOptions\"\n :key=\"option.value\"\n role=\"option\"\n :id=\"`${selectId}-option-${index}`\"\n :aria-selected=\"option.value === modelValue\"\n :aria-disabled=\"option.disabled || undefined\"\n :data-selected=\"option.value === modelValue || undefined\"\n :data-disabled=\"option.disabled || undefined\"\n :class=\"[\n 'rp-select__option',\n {\n 'rp-select__option--selected': option.value === modelValue,\n 'rp-select__option--focused': index === focusedIndex,\n 'rp-select__option--disabled': option.disabled,\n },\n ]\"\n @click=\"selectOption(option)\"\n @mouseenter=\"onOptionMouseenter(option, index)\"\n >\n {{ option.label }}\n </div>\n </div>\n </Transition>\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport ChevronsUpDownIcon from '~icons/lucide/chevrons-up-down';\nimport XIcon from '~icons/lucide/x';\nimport { useSelect } from './useSelect';\nimport type { SelectProps } from './types';\n\ndefineOptions({ name: 'RpSelect' });\n\nconst props = withDefaults(defineProps<SelectProps>(), {\n options: () => [],\n placeholder: 'Select...',\n clearable: false,\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number | null];\n}>();\n\nconst {\n selectRef,\n triggerRef,\n isOpen,\n selectId,\n listboxId,\n control,\n visibleOptions,\n focusedIndex,\n activeDescendantId,\n rootClass,\n hasValue,\n displayLabel,\n canClear,\n toggle,\n selectOption,\n clearSelection,\n onOptionMouseenter,\n onTriggerKeydown,\n} = useSelect(props, (value) => {\n emit('update:modelValue', value);\n});\n\nvoid selectRef;\nvoid triggerRef;\n</script>\n\n<style src=\"./select.scss\" lang=\"scss\" scoped></style>\n"],"mappings":"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"}
package/dist/switch.css CHANGED
@@ -1,23 +1,30 @@
1
- .rp-switch[data-v-8d0cc56f] {
1
+ .rp-switch[data-v-aeef0d94] {
2
+ --_switch-color: var(--rp-color-primary);
3
+ --_switch-font-size: var(--rp-font-size-base);
4
+ --_track-w: 40px;
5
+ --_track-h: 22px;
6
+ --_thumb-size: 18px;
7
+ --_thumb-offset: 2px;
8
+ --_track-bg: var(--rp-color-border);
9
+ --_thumb-bg: #ffffff;
2
10
  display: inline-flex;
3
11
  align-items: center;
4
12
  cursor: pointer;
5
13
  font-family: var(--rp-font-family);
6
14
  user-select: none;
7
15
  }
8
- .rp-switch--disabled[data-v-8d0cc56f] {
16
+ .rp-switch--disabled[data-v-aeef0d94] {
9
17
  opacity: var(--rp-opacity-disabled);
10
18
  cursor: not-allowed;
11
19
  }
12
- .rp-switch[data-v-8d0cc56f] {
20
+ .rp-switch[data-v-aeef0d94] {
13
21
  gap: var(--rp-spacing-2);
14
- font-size: var(--rp-font-size-base);
15
- --_track-w: 40px;
16
- --_track-h: 22px;
17
- --_thumb-size: 18px;
18
- --_thumb-offset: 2px;
22
+ font-size: var(--_switch-font-size);
23
+ }
24
+ html.dark .rp-switch[data-v-aeef0d94] {
25
+ --_thumb-bg: var(--rp-color-surface-inverted);
19
26
  }
20
- .rp-switch__native[data-v-8d0cc56f] {
27
+ .rp-switch__native[data-v-aeef0d94] {
21
28
  position: absolute;
22
29
  width: 1px;
23
30
  height: 1px;
@@ -29,42 +36,90 @@
29
36
  border-width: 0;
30
37
  pointer-events: none;
31
38
  }
32
- .rp-switch__native:focus-visible + .rp-switch__track[data-v-8d0cc56f] {
33
- border-color: var(--rp-color-control-border-focus);
39
+ .rp-switch__native:focus-visible + .rp-switch__track[data-v-aeef0d94] {
40
+ border-color: var(--rp-color-primary);
34
41
  box-shadow: 0 0 0 var(--rp-border-width-medium) var(--rp-color-focus-ring);
35
42
  }
36
- .rp-switch__track[data-v-8d0cc56f] {
43
+ .rp-switch__track[data-v-aeef0d94] {
37
44
  position: relative;
38
45
  display: inline-flex;
39
46
  align-items: center;
40
47
  width: var(--_track-w);
41
48
  height: var(--_track-h);
42
49
  flex-shrink: 0;
43
- background-color: var(--rp-color-control-track-bg);
50
+ background-color: var(--_track-bg);
44
51
  border-radius: var(--rp-radius-full);
45
52
  transition: background-color var(--rp-transition-fast);
46
53
  }
47
- .rp-switch--checked .rp-switch__track[data-v-8d0cc56f] {
48
- background-color: var(--rp-color-control-selected-bg);
54
+ .rp-switch--checked .rp-switch__track[data-v-aeef0d94] {
55
+ background-color: var(--_switch-color);
49
56
  }
50
- .rp-switch--invalid .rp-switch__track[data-v-8d0cc56f] {
57
+ .rp-switch--invalid .rp-switch__track[data-v-aeef0d94] {
51
58
  outline: var(--rp-border-width-thin) solid var(--rp-color-danger-fg);
52
59
  outline-offset: var(--_thumb-offset);
53
60
  }
54
- .rp-switch__thumb[data-v-8d0cc56f] {
61
+ .rp-switch__thumb[data-v-aeef0d94] {
55
62
  position: absolute;
56
63
  left: var(--_thumb-offset);
57
64
  width: var(--_thumb-size);
58
65
  height: var(--_thumb-size);
59
- background-color: var(--rp-color-control-thumb-bg);
66
+ background-color: var(--_thumb-bg);
60
67
  border-radius: var(--rp-radius-full);
61
68
  box-shadow: var(--rp-shadow-sm);
62
69
  transition: transform var(--rp-transition-fast);
63
70
  }
64
- .rp-switch--checked .rp-switch__thumb[data-v-8d0cc56f] {
71
+ .rp-switch--checked .rp-switch__thumb[data-v-aeef0d94] {
65
72
  transform: translateX(calc(var(--_track-w) - var(--_thumb-size) - var(--_thumb-offset) * 2));
66
73
  }
67
- .rp-switch__label[data-v-8d0cc56f] {
74
+ .rp-switch__label[data-v-aeef0d94] {
68
75
  line-height: var(--rp-line-height-normal);
69
76
  color: var(--rp-color-text);
77
+ }
78
+ .rp-switch--color-primary[data-v-aeef0d94] {
79
+ --_switch-color: var(--rp-color-primary);
80
+ }
81
+ .rp-switch--color-secondary[data-v-aeef0d94] {
82
+ --_switch-color: var(--rp-color-secondary);
83
+ }
84
+ .rp-switch--color-success[data-v-aeef0d94] {
85
+ --_switch-color: var(--rp-color-success);
86
+ }
87
+ .rp-switch--color-warning[data-v-aeef0d94] {
88
+ --_switch-color: var(--rp-color-warning);
89
+ }
90
+ .rp-switch--color-danger[data-v-aeef0d94] {
91
+ --_switch-color: var(--rp-color-danger);
92
+ }
93
+ .rp-switch--color-info[data-v-aeef0d94] {
94
+ --_switch-color: var(--rp-color-info);
95
+ }
96
+ .rp-switch--size-xs[data-v-aeef0d94] {
97
+ --_track-w: 28px;
98
+ --_track-h: 16px;
99
+ --_thumb-size: 12px;
100
+ --_switch-font-size: var(--rp-font-size-xs);
101
+ }
102
+ .rp-switch--size-sm[data-v-aeef0d94] {
103
+ --_track-w: 34px;
104
+ --_track-h: 18px;
105
+ --_thumb-size: 14px;
106
+ --_switch-font-size: var(--rp-font-size-sm);
107
+ }
108
+ .rp-switch--size-md[data-v-aeef0d94] {
109
+ --_track-w: 40px;
110
+ --_track-h: 22px;
111
+ --_thumb-size: 18px;
112
+ --_switch-font-size: var(--rp-font-size-base);
113
+ }
114
+ .rp-switch--size-lg[data-v-aeef0d94] {
115
+ --_track-w: 48px;
116
+ --_track-h: 26px;
117
+ --_thumb-size: 22px;
118
+ --_switch-font-size: var(--rp-font-size-lg);
119
+ }
120
+ .rp-switch--size-xl[data-v-aeef0d94] {
121
+ --_track-w: 56px;
122
+ --_track-h: 30px;
123
+ --_thumb-size: 26px;
124
+ --_switch-font-size: var(--rp-font-size-xl);
70
125
  }