ropav 0.0.3 → 0.0.4
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.
- package/dist/base.css +39 -0
- package/dist/button.css +17 -0
- package/dist/button.js +6 -17
- package/dist/button.js.map +1 -1
- package/dist/checkbox.css +9 -5
- package/dist/checkbox.js +11 -33
- package/dist/checkbox.js.map +1 -1
- package/dist/components/button/types.d.ts +1 -1
- package/dist/components/checkbox/types.d.ts +1 -1
- package/dist/components/radio/types.d.ts +1 -1
- package/dist/components/switch/types.d.ts +1 -1
- package/dist/input.css +24 -14
- package/dist/radio.css +9 -5
- package/dist/radio.js.map +1 -1
- package/dist/select.css +11 -11
- package/dist/select.js +11 -33
- package/dist/select.js.map +1 -1
- package/dist/switch.css +6 -6
- package/dist/textarea.css +23 -13
- package/package.json +3 -2
- package/src/styles/_mixins.scss +3 -3
- package/src/styles/_tokens.scss +41 -0
- package/src/styles/_variables.scss +2 -0
package/dist/base.css
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
--rp-color-warning: #cc4e00;
|
|
7
7
|
--rp-color-danger: #ce2c31;
|
|
8
8
|
--rp-color-info: #107d98;
|
|
9
|
+
--rp-color-neutral: #646464;
|
|
9
10
|
--rp-color-text: #202020;
|
|
10
11
|
--rp-color-text-secondary: #646464;
|
|
11
12
|
--rp-color-text-disabled: #8d8d8d;
|
|
@@ -23,12 +24,25 @@
|
|
|
23
24
|
--rp-color-border: #d9d9d9;
|
|
24
25
|
--rp-color-border-hover: #bbbbbb;
|
|
25
26
|
--rp-color-focus-ring: color-mix(in srgb, var(--rp-color-primary) 32%, transparent);
|
|
27
|
+
--rp-color-control-bg: #f9f9f9;
|
|
28
|
+
--rp-color-control-readonly-bg: var(--rp-color-surface-muted);
|
|
29
|
+
--rp-color-control-fg: var(--rp-color-text);
|
|
30
|
+
--rp-color-control-placeholder: var(--rp-color-text-secondary);
|
|
31
|
+
--rp-color-control-icon: var(--rp-color-text-secondary);
|
|
32
|
+
--rp-color-control-border: var(--rp-color-border);
|
|
33
|
+
--rp-color-control-border-hover: var(--rp-color-border-hover);
|
|
34
|
+
--rp-color-control-border-focus: var(--rp-color-primary);
|
|
35
|
+
--rp-color-control-track-bg: var(--rp-color-border);
|
|
36
|
+
--rp-color-control-thumb-bg: #ffffff;
|
|
37
|
+
--rp-color-control-selected-bg: var(--rp-color-primary);
|
|
38
|
+
--rp-color-control-selected-fg: var(--rp-color-on-primary);
|
|
26
39
|
--rp-color-on-primary: #ffffff;
|
|
27
40
|
--rp-color-on-secondary: #ffffff;
|
|
28
41
|
--rp-color-on-success: #ffffff;
|
|
29
42
|
--rp-color-on-warning: #ffffff;
|
|
30
43
|
--rp-color-on-danger: #ffffff;
|
|
31
44
|
--rp-color-on-info: #ffffff;
|
|
45
|
+
--rp-color-on-neutral: #ffffff;
|
|
32
46
|
--rp-color-primary-hover: color-mix(in srgb, var(--rp-color-primary) 90%, #111111);
|
|
33
47
|
--rp-color-primary-active: color-mix(in srgb, var(--rp-color-primary) 80%, #111111);
|
|
34
48
|
--rp-color-primary-subtle-bg: #e6f4fe;
|
|
@@ -77,6 +91,14 @@
|
|
|
77
91
|
--rp-color-info-border: #7dcedc;
|
|
78
92
|
--rp-color-info-border-hover: #3db9cf;
|
|
79
93
|
--rp-color-info-fg: #0d3c48;
|
|
94
|
+
--rp-color-neutral-hover: color-mix(in srgb, var(--rp-color-neutral) 90%, #111111);
|
|
95
|
+
--rp-color-neutral-active: color-mix(in srgb, var(--rp-color-neutral) 80%, #111111);
|
|
96
|
+
--rp-color-neutral-subtle-bg: #f0f0f0;
|
|
97
|
+
--rp-color-neutral-subtle-bg-hover: #e8e8e8;
|
|
98
|
+
--rp-color-neutral-subtle-bg-active: #e0e0e0;
|
|
99
|
+
--rp-color-neutral-border: #cecece;
|
|
100
|
+
--rp-color-neutral-border-hover: #bbbbbb;
|
|
101
|
+
--rp-color-neutral-fg: #202020;
|
|
80
102
|
--rp-font-size-xs: 0.75rem;
|
|
81
103
|
--rp-font-size-sm: 0.875rem;
|
|
82
104
|
--rp-font-size-base: 1rem;
|
|
@@ -114,6 +136,7 @@
|
|
|
114
136
|
--rp-size-control-sm: 32px;
|
|
115
137
|
--rp-size-control-md: 40px;
|
|
116
138
|
--rp-size-control-lg: 48px;
|
|
139
|
+
--rp-opacity-disabled: 0.5;
|
|
117
140
|
--rp-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
|
118
141
|
--rp-shadow-base: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);
|
|
119
142
|
--rp-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
|
|
@@ -141,6 +164,16 @@ html.dark {
|
|
|
141
164
|
--rp-color-border: #3a3a3a;
|
|
142
165
|
--rp-color-border-hover: #606060;
|
|
143
166
|
--rp-color-focus-ring: color-mix(in srgb, var(--rp-color-primary) 45%, transparent);
|
|
167
|
+
--rp-color-control-bg: #191919;
|
|
168
|
+
--rp-color-control-readonly-bg: var(--rp-color-surface-muted);
|
|
169
|
+
--rp-color-control-fg: #eeeeee;
|
|
170
|
+
--rp-color-control-placeholder: #6e6e6e;
|
|
171
|
+
--rp-color-control-icon: #b4b4b4;
|
|
172
|
+
--rp-color-control-border: #3a3a3a;
|
|
173
|
+
--rp-color-control-border-hover: #606060;
|
|
174
|
+
--rp-color-control-border-focus: var(--rp-color-primary);
|
|
175
|
+
--rp-color-control-track-bg: var(--rp-color-border);
|
|
176
|
+
--rp-color-control-thumb-bg: var(--rp-color-surface-inverted);
|
|
144
177
|
--rp-color-primary-subtle-bg: #0d2847;
|
|
145
178
|
--rp-color-primary-subtle-bg-hover: #003362;
|
|
146
179
|
--rp-color-primary-subtle-bg-active: #004074;
|
|
@@ -177,6 +210,12 @@ html.dark {
|
|
|
177
210
|
--rp-color-info-border: #12677e;
|
|
178
211
|
--rp-color-info-border-hover: #11809c;
|
|
179
212
|
--rp-color-info-fg: #4ccce6;
|
|
213
|
+
--rp-color-neutral-subtle-bg: #222222;
|
|
214
|
+
--rp-color-neutral-subtle-bg-hover: #2a2a2a;
|
|
215
|
+
--rp-color-neutral-subtle-bg-active: #313131;
|
|
216
|
+
--rp-color-neutral-border: #484848;
|
|
217
|
+
--rp-color-neutral-border-hover: #606060;
|
|
218
|
+
--rp-color-neutral-fg: #eeeeee;
|
|
180
219
|
--rp-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
|
|
181
220
|
--rp-shadow-base: 0 1px 3px 0 rgba(0, 0, 0, 0.4), 0 1px 2px -1px rgba(0, 0, 0, 0.3);
|
|
182
221
|
--rp-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -2px rgba(0, 0, 0, 0.3);
|
package/dist/button.css
CHANGED
|
@@ -158,6 +158,23 @@
|
|
|
158
158
|
--_rp-button-border-hover: var(--_rp-button-accent-border-hover);
|
|
159
159
|
--_rp-button-fg: var(--_rp-button-accent-fg);
|
|
160
160
|
}
|
|
161
|
+
.rp-button--color-neutral[data-v-b8d57358] {
|
|
162
|
+
--_rp-button-accent: var(--rp-color-neutral);
|
|
163
|
+
--_rp-button-accent-hover: var(--rp-color-neutral-hover);
|
|
164
|
+
--_rp-button-accent-active: var(--rp-color-neutral-active);
|
|
165
|
+
--_rp-button-accent-on: var(--rp-color-on-neutral);
|
|
166
|
+
--_rp-button-accent-subtle-bg: var(--rp-color-neutral-subtle-bg);
|
|
167
|
+
--_rp-button-accent-subtle-bg-hover: var(--rp-color-neutral-subtle-bg-hover);
|
|
168
|
+
--_rp-button-accent-subtle-bg-active: var(--rp-color-neutral-subtle-bg-active);
|
|
169
|
+
--_rp-button-accent-border: var(--rp-color-neutral-border);
|
|
170
|
+
--_rp-button-accent-border-hover: var(--rp-color-neutral-border-hover);
|
|
171
|
+
--_rp-button-accent-fg: var(--rp-color-neutral-fg);
|
|
172
|
+
--_rp-button-bg-hover: var(--_rp-button-accent-subtle-bg-hover);
|
|
173
|
+
--_rp-button-bg-active: var(--_rp-button-accent-subtle-bg-active);
|
|
174
|
+
--_rp-button-border: var(--_rp-button-accent-border);
|
|
175
|
+
--_rp-button-border-hover: var(--_rp-button-accent-border-hover);
|
|
176
|
+
--_rp-button-fg: var(--_rp-button-accent-fg);
|
|
177
|
+
}
|
|
161
178
|
.rp-button--size-xs[data-v-b8d57358] {
|
|
162
179
|
--_rp-button-height: calc(var(--rp-size-control-sm) - var(--rp-spacing-1));
|
|
163
180
|
--_rp-button-padding-x: var(--rp-spacing-2);
|
package/dist/button.js
CHANGED
|
@@ -1,26 +1,15 @@
|
|
|
1
1
|
import './button.css';
|
|
2
2
|
import { n as bem, t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper.js";
|
|
3
|
-
import { child, computed, createComponent,
|
|
3
|
+
import { child, computed, createComponent, createIf, createSlot, defineVaporComponent, markRaw, renderEffect, setClass, setInsertionState, setProp, template, unref } from "vue";
|
|
4
4
|
//#region ~icons/lucide/loader-circle
|
|
5
|
-
var
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
height: "1.2em"
|
|
9
|
-
};
|
|
10
|
-
function render(_ctx, _cache) {
|
|
11
|
-
return openBlock(), createElementBlock("svg", _hoisted_1, [..._cache[0] || (_cache[0] = [createElementVNode("path", {
|
|
12
|
-
fill: "none",
|
|
13
|
-
stroke: "currentColor",
|
|
14
|
-
"stroke-linecap": "round",
|
|
15
|
-
"stroke-linejoin": "round",
|
|
16
|
-
"stroke-width": "2",
|
|
17
|
-
d: "M21 12a9 9 0 1 1-6.219-8.56"
|
|
18
|
-
}, null, -1)])]);
|
|
5
|
+
var t0$1 = template("<svg viewBox=\"0 0 24 24\"width=1.2em height=1.2em><path fill=none stroke=currentColor stroke-linecap=round stroke-linejoin=round stroke-width=2 d=\"M21 12a9 9 0 1 1-6.219-8.56\">", 3, 1);
|
|
6
|
+
function render(_ctx) {
|
|
7
|
+
return t0$1();
|
|
19
8
|
}
|
|
20
|
-
var loader_circle_default = markRaw({
|
|
9
|
+
var loader_circle_default = markRaw(defineVaporComponent({
|
|
21
10
|
name: "lucide-loader-circle",
|
|
22
11
|
render
|
|
23
|
-
});
|
|
12
|
+
}));
|
|
24
13
|
//#endregion
|
|
25
14
|
//#region src/components/button/button.vue?vue&type=script&setup=true&vapor=true&lang.ts
|
|
26
15
|
var t0 = template("<span data-v-b8d57358 class=rp-button__left>");
|
package/dist/button.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.js","names":[],"sources":["../src/components/button/button.vue","../src/components/button/button.vue"],"sourcesContent":["<template>\n <button :class=\"rootClass\" :disabled=\"disabled || isLoading || undefined\" :type=\"type\">\n <IconLoaderCircle v-if=\"isLoading\" class=\"rp-button__spinner\" aria-hidden=\"true\" />\n <span v-if=\"$slots.left && !isLoading\" class=\"rp-button__left\">\n <slot name=\"left\" />\n </span>\n <span class=\"rp-button__label\">\n <slot />\n </span>\n <span v-if=\"$slots.right\" class=\"rp-button__right\">\n <slot name=\"right\" />\n </span>\n </button>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { computed } from 'vue';\nimport IconLoaderCircle from '~icons/lucide/loader-circle';\nimport { bem } from '@/utils/bem';\nimport type { ButtonProps } from './types';\n\ndefineOptions({ name: 'RpButton' });\n\nconst props = withDefaults(defineProps<ButtonProps>(), {\n type: 'button',\n disabled: false,\n loading: false,\n});\n\nconst isLoading = computed(() => props.loading && !props.disabled);\n\nconst rootClass = computed(() =>\n bem('rp-button', {\n [props.variant ?? '']: Boolean(props.variant),\n [`color-${props.color}`]: Boolean(props.color),\n [`size-${props.size}`]: Boolean(props.size),\n [`radius-${props.radius}`]: Boolean(props.radius),\n }),\n);\n</script>\n\n<style src=\"./button.scss\" lang=\"scss\" scoped></style>\n","<template>\n <button :class=\"rootClass\" :disabled=\"disabled || isLoading || undefined\" :type=\"type\">\n <IconLoaderCircle v-if=\"isLoading\" class=\"rp-button__spinner\" aria-hidden=\"true\" />\n <span v-if=\"$slots.left && !isLoading\" class=\"rp-button__left\">\n <slot name=\"left\" />\n </span>\n <span class=\"rp-button__label\">\n <slot />\n </span>\n <span v-if=\"$slots.right\" class=\"rp-button__right\">\n <slot name=\"right\" />\n </span>\n </button>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { computed } from 'vue';\nimport IconLoaderCircle from '~icons/lucide/loader-circle';\nimport { bem } from '@/utils/bem';\nimport type { ButtonProps } from './types';\n\ndefineOptions({ name: 'RpButton' });\n\nconst props = withDefaults(defineProps<ButtonProps>(), {\n type: 'button',\n disabled: false,\n loading: false,\n});\n\nconst isLoading = computed(() => props.loading && !props.disabled);\n\nconst rootClass = computed(() =>\n bem('rp-button', {\n [props.variant ?? '']: Boolean(props.variant),\n [`color-${props.color}`]: Boolean(props.color),\n [`size-${props.size}`]: Boolean(props.size),\n [`radius-${props.radius}`]: Boolean(props.radius),\n }),\n);\n</script>\n\n<style src=\"./button.scss\" lang=\"scss\" scoped></style>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"button.js","names":[],"sources":["../src/components/button/button.vue","../src/components/button/button.vue"],"sourcesContent":["<template>\n <button :class=\"rootClass\" :disabled=\"disabled || isLoading || undefined\" :type=\"type\">\n <IconLoaderCircle v-if=\"isLoading\" class=\"rp-button__spinner\" aria-hidden=\"true\" />\n <span v-if=\"$slots.left && !isLoading\" class=\"rp-button__left\">\n <slot name=\"left\" />\n </span>\n <span class=\"rp-button__label\">\n <slot />\n </span>\n <span v-if=\"$slots.right\" class=\"rp-button__right\">\n <slot name=\"right\" />\n </span>\n </button>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { computed } from 'vue';\nimport IconLoaderCircle from '~icons/lucide/loader-circle';\nimport { bem } from '@/utils/bem';\nimport type { ButtonProps } from './types';\n\ndefineOptions({ name: 'RpButton' });\n\nconst props = withDefaults(defineProps<ButtonProps>(), {\n type: 'button',\n disabled: false,\n loading: false,\n});\n\nconst isLoading = computed(() => props.loading && !props.disabled);\n\nconst rootClass = computed(() =>\n bem('rp-button', {\n [props.variant ?? '']: Boolean(props.variant),\n [`color-${props.color}`]: Boolean(props.color),\n [`size-${props.size}`]: Boolean(props.size),\n [`radius-${props.radius}`]: Boolean(props.radius),\n }),\n);\n</script>\n\n<style src=\"./button.scss\" lang=\"scss\" scoped></style>\n","<template>\n <button :class=\"rootClass\" :disabled=\"disabled || isLoading || undefined\" :type=\"type\">\n <IconLoaderCircle v-if=\"isLoading\" class=\"rp-button__spinner\" aria-hidden=\"true\" />\n <span v-if=\"$slots.left && !isLoading\" class=\"rp-button__left\">\n <slot name=\"left\" />\n </span>\n <span class=\"rp-button__label\">\n <slot />\n </span>\n <span v-if=\"$slots.right\" class=\"rp-button__right\">\n <slot name=\"right\" />\n </span>\n </button>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { computed } from 'vue';\nimport IconLoaderCircle from '~icons/lucide/loader-circle';\nimport { bem } from '@/utils/bem';\nimport type { ButtonProps } from './types';\n\ndefineOptions({ name: 'RpButton' });\n\nconst props = withDefaults(defineProps<ButtonProps>(), {\n type: 'button',\n disabled: false,\n loading: false,\n});\n\nconst isLoading = computed(() => props.loading && !props.disabled);\n\nconst rootClass = computed(() =>\n bem('rp-button', {\n [props.variant ?? '']: Boolean(props.variant),\n [`color-${props.color}`]: Boolean(props.color),\n [`size-${props.size}`]: Boolean(props.size),\n [`radius-${props.radius}`]: Boolean(props.radius),\n }),\n);\n</script>\n\n<style src=\"./button.scss\" lang=\"scss\" scoped></style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBA,MAAM,QAAQ;EAMd,MAAM,YAAY,eAAe,MAAM,WAAW,CAAC,MAAM,QAAQ;EAEjE,MAAM,YAAY,eACd,IAAI,aAAa;IACZ,MAAM,WAAW,KAAK,QAAQ,MAAM,OAAO;IAC3C,SAAS,MAAM,UAAU,QAAQ,MAAM,KAAK;IAC5C,QAAQ,MAAM,SAAS,QAAQ,MAAM,IAAI;IACzC,UAAU,MAAM,WAAW,QAAQ,MAAM,MAAM;EACpD,CAAC,CACL;;;;iBArCoB,UAAA,KAAS;gBAAG,YAAU,QAAA,YAAY,UAAA,SAAa,KAAA,CAAS;gBAAG,QAAM,QAAA,IAAI;;;iBACzD,UAAA,aAAS;;IAAE,OAAM;IAAqB,eAAY;;;;iBAC9D,OAAM,QAAA,CAAU,UAAA,aAAS;;;cAC3B,QAAW,MAAA,MAAA,CAAA;;;;;;iBAKT,OAAM,aAAA;;;cACR,SAAY,MAAA,MAAA,CAAA"}
|
package/dist/checkbox.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
.rp-checkbox[data-v-7333dac7] {
|
|
2
|
-
--_checkbox-color: var(--rp-color-
|
|
3
|
-
--_checkbox-on-color: var(--rp-color-
|
|
2
|
+
--_checkbox-color: var(--rp-color-control-selected-bg);
|
|
3
|
+
--_checkbox-on-color: var(--rp-color-control-selected-fg);
|
|
4
4
|
--_checkbox-size: 18px;
|
|
5
5
|
--_checkbox-icon-size: 14px;
|
|
6
6
|
--_checkbox-font-size: var(--rp-font-size-base);
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
width: var(--_checkbox-size);
|
|
46
46
|
height: var(--_checkbox-size);
|
|
47
47
|
flex-shrink: 0;
|
|
48
|
-
border: var(--rp-border-width-medium) solid var(--rp-color-border);
|
|
48
|
+
border: var(--rp-border-width-medium) solid var(--rp-color-control-border);
|
|
49
49
|
border-radius: var(--_checkbox-radius);
|
|
50
|
-
background-color: var(--rp-color-
|
|
50
|
+
background-color: var(--rp-color-control-bg);
|
|
51
51
|
transition: background-color var(--rp-transition-fast), border-color var(--rp-transition-fast);
|
|
52
52
|
}
|
|
53
53
|
.rp-checkbox--checked .rp-checkbox__box[data-v-7333dac7], .rp-checkbox--indeterminate .rp-checkbox__box[data-v-7333dac7] {
|
|
@@ -94,8 +94,12 @@
|
|
|
94
94
|
--_checkbox-color: var(--rp-color-info);
|
|
95
95
|
--_checkbox-on-color: var(--rp-color-on-info);
|
|
96
96
|
}
|
|
97
|
+
.rp-checkbox--color-neutral[data-v-7333dac7] {
|
|
98
|
+
--_checkbox-color: var(--rp-color-neutral);
|
|
99
|
+
--_checkbox-on-color: var(--rp-color-on-neutral);
|
|
100
|
+
}
|
|
97
101
|
.rp-checkbox--outline[data-v-7333dac7] {
|
|
98
|
-
--_checkbox-checked-bg: var(--rp-color-
|
|
102
|
+
--_checkbox-checked-bg: var(--rp-color-control-bg);
|
|
99
103
|
--_checkbox-checked-border: var(--_checkbox-color);
|
|
100
104
|
--_checkbox-checked-icon: var(--_checkbox-color);
|
|
101
105
|
}
|
package/dist/checkbox.js
CHANGED
|
@@ -1,48 +1,26 @@
|
|
|
1
1
|
import './checkbox.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,
|
|
4
|
+
import { VaporTransition, child, computed, createComponent, createIf, createSlot, defineVaporComponent, extend, markRaw, next, on, renderEffect, setAttr, setBlockKey, setClass, setInsertionState, setProp, template, unref } from "vue";
|
|
5
5
|
//#region ~icons/lucide/check
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
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: "M20 6L9 17l-5-5"
|
|
19
|
-
}, null, -1)])]);
|
|
6
|
+
var t0$2 = template("<svg viewBox=\"0 0 24 24\"width=1.2em height=1.2em><path fill=none stroke=currentColor stroke-linecap=round stroke-linejoin=round stroke-width=2 d=\"M20 6L9 17l-5-5\">", 3, 1);
|
|
7
|
+
function render$1(_ctx) {
|
|
8
|
+
return t0$2();
|
|
20
9
|
}
|
|
21
|
-
var check_default = markRaw({
|
|
10
|
+
var check_default = markRaw(defineVaporComponent({
|
|
22
11
|
name: "lucide-check",
|
|
23
12
|
render: render$1
|
|
24
|
-
});
|
|
13
|
+
}));
|
|
25
14
|
//#endregion
|
|
26
15
|
//#region ~icons/lucide/minus
|
|
27
|
-
var
|
|
28
|
-
|
|
29
|
-
|
|
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: "M5 12h14"
|
|
40
|
-
}, null, -1)])]);
|
|
16
|
+
var t0$1 = template("<svg viewBox=\"0 0 24 24\"width=1.2em height=1.2em><path fill=none stroke=currentColor stroke-linecap=round stroke-linejoin=round stroke-width=2 d=\"M5 12h14\">", 3, 1);
|
|
17
|
+
function render(_ctx) {
|
|
18
|
+
return t0$1();
|
|
41
19
|
}
|
|
42
|
-
var minus_default = markRaw({
|
|
20
|
+
var minus_default = markRaw(defineVaporComponent({
|
|
43
21
|
name: "lucide-minus",
|
|
44
22
|
render
|
|
45
|
-
});
|
|
23
|
+
}));
|
|
46
24
|
//#endregion
|
|
47
25
|
//#region src/components/checkbox/useCheckbox.ts
|
|
48
26
|
function useCheckbox(props, emitUpdate) {
|
package/dist/checkbox.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkbox.js","names":[],"sources":["../src/components/checkbox/useCheckbox.ts","../src/components/checkbox/checkbox.vue","../src/components/checkbox/checkbox.vue"],"sourcesContent":["import { computed } from 'vue';\nimport { useControlState } from '@/composables/useControlState';\nimport { bem } from '@/utils/bem';\nimport type { CheckboxProps } from './types';\n\nexport function useCheckbox(props: Readonly<CheckboxProps>, emitUpdate: (value: boolean) => void) {\n const control = useControlState(props);\n\n const rootClass = computed(() =>\n bem('rp-checkbox', {\n checked: props.modelValue,\n indeterminate: props.indeterminate,\n disabled: control.disabled,\n invalid: control.invalid,\n [props.variant ?? '']: Boolean(props.variant),\n [`color-${props.color}`]: Boolean(props.color),\n [`size-${props.size}`]: Boolean(props.size),\n [`radius-${props.radius}`]: Boolean(props.radius),\n }),\n );\n\n function onChange(e: Event) {\n emitUpdate((e.target as HTMLInputElement).checked);\n }\n\n return {\n control,\n rootClass,\n onChange,\n };\n}\n","<template>\n <label\n :class=\"rootClass\"\n :data-disabled=\"control.disabled || undefined\"\n :data-state=\"indeterminate ? 'indeterminate' : modelValue ? 'checked' : 'unchecked'\"\n >\n <input\n :id=\"control.id\"\n :name=\"name\"\n type=\"checkbox\"\n class=\"rp-checkbox__native\"\n :checked=\"modelValue\"\n :disabled=\"control.disabled || undefined\"\n :required=\"control.required || undefined\"\n :indeterminate=\"indeterminate\"\n :aria-checked=\"indeterminate ? 'mixed' : modelValue\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n @change=\"onChange\"\n />\n <span class=\"rp-checkbox__box\">\n <Transition name=\"rp-checkbox-icon\" mode=\"out-in\">\n <MinusIcon v-if=\"indeterminate\" key=\"minus\" class=\"rp-checkbox__icon\" />\n <CheckIcon v-else-if=\"modelValue\" key=\"check\" class=\"rp-checkbox__icon\" />\n </Transition>\n </span>\n <span v-if=\"$slots.default\" class=\"rp-checkbox__label\">\n <slot />\n </span>\n </label>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport CheckIcon from '~icons/lucide/check';\nimport MinusIcon from '~icons/lucide/minus';\nimport { useCheckbox } from './useCheckbox';\nimport type { CheckboxProps } from './types';\n\ndefineOptions({ name: 'RpCheckbox' });\n\nconst props = withDefaults(defineProps<CheckboxProps>(), {\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n indeterminate: false,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst { control, rootClass, onChange } = useCheckbox(props, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./checkbox.scss\" lang=\"scss\" scoped></style>\n","<template>\n <label\n :class=\"rootClass\"\n :data-disabled=\"control.disabled || undefined\"\n :data-state=\"indeterminate ? 'indeterminate' : modelValue ? 'checked' : 'unchecked'\"\n >\n <input\n :id=\"control.id\"\n :name=\"name\"\n type=\"checkbox\"\n class=\"rp-checkbox__native\"\n :checked=\"modelValue\"\n :disabled=\"control.disabled || undefined\"\n :required=\"control.required || undefined\"\n :indeterminate=\"indeterminate\"\n :aria-checked=\"indeterminate ? 'mixed' : modelValue\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n @change=\"onChange\"\n />\n <span class=\"rp-checkbox__box\">\n <Transition name=\"rp-checkbox-icon\" mode=\"out-in\">\n <MinusIcon v-if=\"indeterminate\" key=\"minus\" class=\"rp-checkbox__icon\" />\n <CheckIcon v-else-if=\"modelValue\" key=\"check\" class=\"rp-checkbox__icon\" />\n </Transition>\n </span>\n <span v-if=\"$slots.default\" class=\"rp-checkbox__label\">\n <slot />\n </span>\n </label>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport CheckIcon from '~icons/lucide/check';\nimport MinusIcon from '~icons/lucide/minus';\nimport { useCheckbox } from './useCheckbox';\nimport type { CheckboxProps } from './types';\n\ndefineOptions({ name: 'RpCheckbox' });\n\nconst props = withDefaults(defineProps<CheckboxProps>(), {\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n indeterminate: false,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst { control, rootClass, onChange } = useCheckbox(props, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./checkbox.scss\" lang=\"scss\" scoped></style>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"checkbox.js","names":[],"sources":["../src/components/checkbox/useCheckbox.ts","../src/components/checkbox/checkbox.vue","../src/components/checkbox/checkbox.vue"],"sourcesContent":["import { computed } from 'vue';\nimport { useControlState } from '@/composables/useControlState';\nimport { bem } from '@/utils/bem';\nimport type { CheckboxProps } from './types';\n\nexport function useCheckbox(props: Readonly<CheckboxProps>, emitUpdate: (value: boolean) => void) {\n const control = useControlState(props);\n\n const rootClass = computed(() =>\n bem('rp-checkbox', {\n checked: props.modelValue,\n indeterminate: props.indeterminate,\n disabled: control.disabled,\n invalid: control.invalid,\n [props.variant ?? '']: Boolean(props.variant),\n [`color-${props.color}`]: Boolean(props.color),\n [`size-${props.size}`]: Boolean(props.size),\n [`radius-${props.radius}`]: Boolean(props.radius),\n }),\n );\n\n function onChange(e: Event) {\n emitUpdate((e.target as HTMLInputElement).checked);\n }\n\n return {\n control,\n rootClass,\n onChange,\n };\n}\n","<template>\n <label\n :class=\"rootClass\"\n :data-disabled=\"control.disabled || undefined\"\n :data-state=\"indeterminate ? 'indeterminate' : modelValue ? 'checked' : 'unchecked'\"\n >\n <input\n :id=\"control.id\"\n :name=\"name\"\n type=\"checkbox\"\n class=\"rp-checkbox__native\"\n :checked=\"modelValue\"\n :disabled=\"control.disabled || undefined\"\n :required=\"control.required || undefined\"\n :indeterminate=\"indeterminate\"\n :aria-checked=\"indeterminate ? 'mixed' : modelValue\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n @change=\"onChange\"\n />\n <span class=\"rp-checkbox__box\">\n <Transition name=\"rp-checkbox-icon\" mode=\"out-in\">\n <MinusIcon v-if=\"indeterminate\" key=\"minus\" class=\"rp-checkbox__icon\" />\n <CheckIcon v-else-if=\"modelValue\" key=\"check\" class=\"rp-checkbox__icon\" />\n </Transition>\n </span>\n <span v-if=\"$slots.default\" class=\"rp-checkbox__label\">\n <slot />\n </span>\n </label>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport CheckIcon from '~icons/lucide/check';\nimport MinusIcon from '~icons/lucide/minus';\nimport { useCheckbox } from './useCheckbox';\nimport type { CheckboxProps } from './types';\n\ndefineOptions({ name: 'RpCheckbox' });\n\nconst props = withDefaults(defineProps<CheckboxProps>(), {\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n indeterminate: false,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst { control, rootClass, onChange } = useCheckbox(props, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./checkbox.scss\" lang=\"scss\" scoped></style>\n","<template>\n <label\n :class=\"rootClass\"\n :data-disabled=\"control.disabled || undefined\"\n :data-state=\"indeterminate ? 'indeterminate' : modelValue ? 'checked' : 'unchecked'\"\n >\n <input\n :id=\"control.id\"\n :name=\"name\"\n type=\"checkbox\"\n class=\"rp-checkbox__native\"\n :checked=\"modelValue\"\n :disabled=\"control.disabled || undefined\"\n :required=\"control.required || undefined\"\n :indeterminate=\"indeterminate\"\n :aria-checked=\"indeterminate ? 'mixed' : modelValue\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n @change=\"onChange\"\n />\n <span class=\"rp-checkbox__box\">\n <Transition name=\"rp-checkbox-icon\" mode=\"out-in\">\n <MinusIcon v-if=\"indeterminate\" key=\"minus\" class=\"rp-checkbox__icon\" />\n <CheckIcon v-else-if=\"modelValue\" key=\"check\" class=\"rp-checkbox__icon\" />\n </Transition>\n </span>\n <span v-if=\"$slots.default\" class=\"rp-checkbox__label\">\n <slot />\n </span>\n </label>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport CheckIcon from '~icons/lucide/check';\nimport MinusIcon from '~icons/lucide/minus';\nimport { useCheckbox } from './useCheckbox';\nimport type { CheckboxProps } from './types';\n\ndefineOptions({ name: 'RpCheckbox' });\n\nconst props = withDefaults(defineProps<CheckboxProps>(), {\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n indeterminate: false,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst { control, rootClass, onChange } = useCheckbox(props, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./checkbox.scss\" lang=\"scss\" scoped></style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAKA,SAAgB,YAAY,OAAgC,YAAsC;CAC9F,MAAM,UAAU,gBAAgB,KAAK;CAErC,MAAM,YAAY,eACd,IAAI,eAAe;EACf,SAAS,MAAM;EACf,eAAe,MAAM;EACrB,UAAU,QAAQ;EAClB,SAAS,QAAQ;GAChB,MAAM,WAAW,KAAK,QAAQ,MAAM,OAAO;GAC3C,SAAS,MAAM,UAAU,QAAQ,MAAM,KAAK;GAC5C,QAAQ,MAAM,SAAS,QAAQ,MAAM,IAAI;GACzC,UAAU,MAAM,WAAW,QAAQ,MAAM,MAAM;CACpD,CAAC,CACL;CAEA,SAAS,SAAS,GAAU;EACxB,WAAY,EAAE,OAA4B,OAAO;CACrD;CAEA,OAAO;EACH;EACA;EACA;CACJ;AACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECaA,MAAM,QAAQ;EAOd,MAAM,OAAO;EAIb,MAAM,EAAE,SAAS,WAAW,aAAa,YAAY,QAAQ,UAAU;GACnE,KAAK,qBAAqB,KAAK;EACnC,CAAC;;;;SAnCY,WAAM,MAAE,MAAA,QAAA,CAAQ,CAAA,CAAA,CAAA;;;;;;;iBAnBb,MAAA,SAAA,CAAS;gBAChB,iBAAe,qBAAoB,KAAA,CAAS;gBAC5C,cAAY,iBAAa,kBAAqB,cAAU,YAAA,WAAA;eAGpD,MAAI,SAAO,EAAA;eACX,QAAM,QAAA,IAAI;eAGV,WAAS,WAAU;eACnB,YAAU,qBAAoB,KAAA,CAAS;eACvC,YAAU,qBAAoB,KAAA,CAAS;eACvC,iBAAe,cAAa;eAC5B,gBAAc,iBAAa,UAAa,WAAU;eAClD,cAAY,QAAA,aAAa,KAAA,CAAS;eAClC,mBAAiB,SAAO,cAAA;eACxB,oBAAkB,SAAO,eAAA;eACzB,gBAAc,SAAO,WAAY,KAAA,CAAS;eAC1C,iBAAe,qBAAoB,KAAA,CAAS;;;;GAIjC,MAAK;GAAmB,MAAK;;yBACpB,QAAA,qBAAa;uDAAc,OAAM,oBAAmB,CAAA;oBAAjC,OAAO;;2BACrB,QAAA,kBAAU;uDAAc,OAAM,oBAAmB,CAAA;oBAAjC,OAAO;;;;;iBAGzC,OAAM,eAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ButtonColor = 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info';
|
|
1
|
+
export type ButtonColor = 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'neutral';
|
|
2
2
|
export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
3
3
|
export type ButtonRadius = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
4
4
|
export type ButtonVariant = 'solid' | 'subtle' | 'surface' | 'outline' | 'ghost' | 'plain';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type CheckboxColor = 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info';
|
|
1
|
+
export type CheckboxColor = 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'neutral';
|
|
2
2
|
export type CheckboxSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
3
3
|
export type CheckboxRadius = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
4
4
|
export type CheckboxVariant = 'solid' | 'outline';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InjectionKey } from 'vue';
|
|
2
|
-
export type RadioColor = 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info';
|
|
2
|
+
export type RadioColor = 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'neutral';
|
|
3
3
|
export type RadioSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
4
4
|
export type RadioVariant = 'solid' | 'outline';
|
|
5
5
|
export interface RadioProps {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type SwitchColor = 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info';
|
|
1
|
+
export type SwitchColor = 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'neutral';
|
|
2
2
|
export type SwitchSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
3
3
|
export interface SwitchProps {
|
|
4
4
|
id?: string;
|
package/dist/input.css
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
--_rp-input-padding-x: var(--rp-spacing-3);
|
|
4
4
|
--_rp-input-font-size: var(--rp-font-size-base);
|
|
5
5
|
--_rp-input-radius: var(--rp-radius-sm);
|
|
6
|
+
--_rp-input-valid-border: var(--rp-color-success-border-hover);
|
|
7
|
+
--_rp-input-valid-ring: color-mix(in srgb, var(--rp-color-success) 32%, transparent);
|
|
8
|
+
--_rp-input-invalid-border: var(--rp-color-danger-border-hover);
|
|
9
|
+
--_rp-input-invalid-ring: color-mix(in srgb, var(--rp-color-danger) 32%, transparent);
|
|
6
10
|
display: inline-flex;
|
|
7
11
|
align-items: center;
|
|
8
12
|
justify-content: center;
|
|
@@ -10,16 +14,16 @@
|
|
|
10
14
|
gap: var(--rp-spacing-2);
|
|
11
15
|
font-family: var(--rp-font-family);
|
|
12
16
|
font-weight: var(--rp-font-weight-normal);
|
|
13
|
-
background-color: var(--rp-color-
|
|
14
|
-
border: var(--rp-border-width-thin) solid var(--rp-color-border);
|
|
17
|
+
background-color: var(--rp-color-control-bg);
|
|
18
|
+
border: var(--rp-border-width-thin) solid var(--rp-color-control-border);
|
|
15
19
|
cursor: text;
|
|
16
20
|
transition: border-color var(--rp-transition-fast), box-shadow var(--rp-transition-fast);
|
|
17
21
|
}
|
|
18
22
|
.rp-input[data-v-fedf15e7]:hover:not(.rp-input--disabled):not(.rp-input--invalid):not(.rp-input--valid) {
|
|
19
|
-
border-color: var(--rp-color-border-hover);
|
|
23
|
+
border-color: var(--rp-color-control-border-hover);
|
|
20
24
|
}
|
|
21
25
|
.rp-input[data-v-fedf15e7]:focus-within:not(.rp-input--disabled):not(.rp-input--invalid):not(.rp-input--valid) {
|
|
22
|
-
border-color: var(--rp-color-
|
|
26
|
+
border-color: var(--rp-color-control-border-focus);
|
|
23
27
|
box-shadow: 0 0 0 var(--rp-border-width-medium) var(--rp-color-focus-ring);
|
|
24
28
|
}
|
|
25
29
|
.rp-input[data-v-fedf15e7] {
|
|
@@ -68,26 +72,32 @@
|
|
|
68
72
|
.rp-input--radius-xl[data-v-fedf15e7] {
|
|
69
73
|
--_rp-input-radius: var(--rp-radius-xl);
|
|
70
74
|
}
|
|
75
|
+
html.dark .rp-input[data-v-fedf15e7] {
|
|
76
|
+
--_rp-input-valid-border: var(--rp-color-success-fg);
|
|
77
|
+
--_rp-input-valid-ring: color-mix(in srgb, var(--rp-color-success-fg) 32%, transparent);
|
|
78
|
+
--_rp-input-invalid-border: var(--rp-color-danger-fg);
|
|
79
|
+
--_rp-input-invalid-ring: color-mix(in srgb, var(--rp-color-danger-fg) 32%, transparent);
|
|
80
|
+
}
|
|
71
81
|
.rp-input--disabled[data-v-fedf15e7] {
|
|
72
82
|
opacity: var(--rp-opacity-disabled);
|
|
73
83
|
cursor: not-allowed;
|
|
74
84
|
}
|
|
75
85
|
.rp-input--valid[data-v-fedf15e7] {
|
|
76
|
-
border-color: var(--
|
|
86
|
+
border-color: var(--_rp-input-valid-border);
|
|
77
87
|
}
|
|
78
88
|
.rp-input--valid[data-v-fedf15e7]:focus-within:not(.rp-input--disabled) {
|
|
79
|
-
border-color: var(--
|
|
80
|
-
box-shadow: 0 0 0 var(--rp-border-width-medium)
|
|
89
|
+
border-color: var(--_rp-input-valid-border);
|
|
90
|
+
box-shadow: 0 0 0 var(--rp-border-width-medium) var(--_rp-input-valid-ring);
|
|
81
91
|
}
|
|
82
92
|
.rp-input--invalid[data-v-fedf15e7] {
|
|
83
|
-
border-color: var(--
|
|
93
|
+
border-color: var(--_rp-input-invalid-border);
|
|
84
94
|
}
|
|
85
95
|
.rp-input--invalid[data-v-fedf15e7]:focus-within:not(.rp-input--disabled) {
|
|
86
|
-
border-color: var(--
|
|
87
|
-
box-shadow: 0 0 0 var(--rp-border-width-medium)
|
|
96
|
+
border-color: var(--_rp-input-invalid-border);
|
|
97
|
+
box-shadow: 0 0 0 var(--rp-border-width-medium) var(--_rp-input-invalid-ring);
|
|
88
98
|
}
|
|
89
99
|
.rp-input--readonly[data-v-fedf15e7] {
|
|
90
|
-
background-color: var(--rp-color-
|
|
100
|
+
background-color: var(--rp-color-control-readonly-bg);
|
|
91
101
|
}
|
|
92
102
|
.rp-input__native[data-v-fedf15e7] {
|
|
93
103
|
box-sizing: border-box;
|
|
@@ -100,11 +110,11 @@
|
|
|
100
110
|
outline: none;
|
|
101
111
|
background: transparent;
|
|
102
112
|
font: inherit;
|
|
103
|
-
color: var(--rp-color-
|
|
113
|
+
color: var(--rp-color-control-fg);
|
|
104
114
|
line-height: var(--rp-line-height-none);
|
|
105
115
|
}
|
|
106
116
|
.rp-input__native[data-v-fedf15e7]::placeholder {
|
|
107
|
-
color: var(--rp-color-
|
|
117
|
+
color: var(--rp-color-control-placeholder);
|
|
108
118
|
}
|
|
109
119
|
.rp-input__native[data-v-fedf15e7]:disabled {
|
|
110
120
|
cursor: not-allowed;
|
|
@@ -113,5 +123,5 @@
|
|
|
113
123
|
display: inline-flex;
|
|
114
124
|
align-items: center;
|
|
115
125
|
flex-shrink: 0;
|
|
116
|
-
color:
|
|
126
|
+
color: var(--rp-color-control-icon);
|
|
117
127
|
}
|
package/dist/radio.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
.rp-radio[data-v-ecddd6c8] {
|
|
2
|
-
--_radio-color: var(--rp-color-
|
|
3
|
-
--_radio-on-color: var(--rp-color-
|
|
2
|
+
--_radio-color: var(--rp-color-control-selected-bg);
|
|
3
|
+
--_radio-on-color: var(--rp-color-control-selected-fg);
|
|
4
4
|
--_radio-size: 18px;
|
|
5
5
|
--_radio-dot: 8px;
|
|
6
6
|
--_radio-font-size: var(--rp-font-size-base);
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
width: var(--_radio-size);
|
|
45
45
|
height: var(--_radio-size);
|
|
46
46
|
flex-shrink: 0;
|
|
47
|
-
border: var(--rp-border-width-medium) solid var(--rp-color-border);
|
|
47
|
+
border: var(--rp-border-width-medium) solid var(--rp-color-control-border);
|
|
48
48
|
border-radius: var(--rp-radius-full);
|
|
49
|
-
background-color: var(--rp-color-
|
|
49
|
+
background-color: var(--rp-color-control-bg);
|
|
50
50
|
transition: background-color var(--rp-transition-fast), border-color var(--rp-transition-fast);
|
|
51
51
|
}
|
|
52
52
|
.rp-radio__dot[data-v-ecddd6c8]::after {
|
|
@@ -93,8 +93,12 @@
|
|
|
93
93
|
--_radio-color: var(--rp-color-info);
|
|
94
94
|
--_radio-on-color: var(--rp-color-on-info);
|
|
95
95
|
}
|
|
96
|
+
.rp-radio--color-neutral[data-v-ecddd6c8] {
|
|
97
|
+
--_radio-color: var(--rp-color-neutral);
|
|
98
|
+
--_radio-on-color: var(--rp-color-on-neutral);
|
|
99
|
+
}
|
|
96
100
|
.rp-radio--outline[data-v-ecddd6c8] {
|
|
97
|
-
--_radio-checked-bg: var(--rp-color-
|
|
101
|
+
--_radio-checked-bg: var(--rp-color-control-bg);
|
|
98
102
|
--_radio-checked-border: var(--_radio-color);
|
|
99
103
|
--_radio-checked-dot: var(--_radio-color);
|
|
100
104
|
}
|
package/dist/radio.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radio.js","names":[],"sources":["../src/composables/useRequiredInject.ts","../src/components/radio/types.ts","../src/components/radio/useRadio.ts","../src/components/radio/radio.vue","../src/components/radio/radio.vue","../src/components/radio/radio-group.vue","../src/components/radio/radio-group.vue"],"sourcesContent":["import { inject, type InjectionKey } from 'vue';\n\nexport function useRequiredInject<T>(key: InjectionKey<T>, componentName: string): T {\n const value = inject(key);\n if (value == null) {\n throw new Error(\n `[Ropav] <${componentName}> must be used inside its parent provider component.`,\n );\n }\n return value;\n}\n","import type { InjectionKey } from 'vue';\n\nexport type RadioColor = 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info';\n\nexport type RadioSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport type RadioVariant = 'solid' | 'outline';\n\nexport interface RadioProps {\n value: string | number;\n variant?: RadioVariant;\n color?: RadioColor;\n size?: RadioSize;\n disabled?: boolean;\n}\n\nexport interface RadioGroupProps {\n id?: string;\n name?: string;\n modelValue: string | number | null;\n variant?: RadioVariant;\n color?: RadioColor;\n size?: RadioSize;\n disabled?: boolean;\n required?: boolean;\n invalid?: boolean;\n ariaLabel?: string;\n describedby?: string;\n labelledby?: string;\n}\n\nexport interface RadioGroupContext {\n modelValue: string | number | null;\n name: string;\n disabled: boolean;\n required: boolean;\n variant?: RadioVariant;\n color?: RadioColor;\n size?: RadioSize;\n select: (value: string | number) => void;\n}\n\nexport const radioGroupKey = Symbol('radioGroup') as InjectionKey<RadioGroupContext>;\n","import { computed, provide, useId } from 'vue';\nimport { useControlState } from '@/composables/useControlState';\nimport { useRequiredInject } from '@/composables/useRequiredInject';\nimport { bem } from '@/utils/bem';\nimport { radioGroupKey } from './types';\nimport type { RadioGroupContext, RadioGroupProps, RadioProps } from './types';\n\nexport function useRadio(props: Readonly<RadioProps>) {\n const group = useRequiredInject(radioGroupKey, 'RpRadio');\n const isChecked = computed(() => group.modelValue === props.value);\n const isDisabled = computed(() => props.disabled || group.disabled);\n const variant = computed(() => props.variant ?? group.variant);\n const color = computed(() => props.color ?? group.color);\n const size = computed(() => props.size ?? group.size);\n\n const rootClass = computed(() =>\n bem('rp-radio', {\n checked: isChecked.value,\n disabled: isDisabled.value,\n [variant.value ?? '']: Boolean(variant.value),\n [`color-${color.value}`]: Boolean(color.value),\n [`size-${size.value}`]: Boolean(size.value),\n }),\n );\n\n function onSelect() {\n if (isDisabled.value) return;\n group.select(props.value);\n }\n\n return {\n group,\n isChecked,\n isDisabled,\n rootClass,\n onSelect,\n };\n}\n\nexport function useRadioGroup(\n props: Readonly<RadioGroupProps>,\n emitUpdate: (value: string | number | null) => void,\n) {\n const control = useControlState(props);\n\n const rootClass = computed(() =>\n bem('rp-radio-group', {\n disabled: control.disabled,\n invalid: control.invalid,\n }),\n );\n\n const generatedName = useId();\n const groupName = computed(() => props.name ?? `${control.id ?? generatedName}-radio`);\n\n provide<RadioGroupContext>(radioGroupKey, {\n get modelValue() {\n return props.modelValue;\n },\n get name() {\n return groupName.value;\n },\n get disabled() {\n return control.disabled;\n },\n get required() {\n return control.required;\n },\n get variant() {\n return props.variant;\n },\n get color() {\n return props.color;\n },\n get size() {\n return props.size;\n },\n select(value) {\n emitUpdate(value);\n },\n });\n\n return {\n control,\n rootClass,\n };\n}\n","<template>\n <label\n :class=\"rootClass\"\n :data-disabled=\"isDisabled || undefined\"\n :data-state=\"isChecked ? 'checked' : 'unchecked'\"\n >\n <input\n type=\"radio\"\n class=\"rp-radio__native\"\n :name=\"group.name\"\n :value=\"value\"\n :checked=\"isChecked\"\n :disabled=\"isDisabled || undefined\"\n :required=\"group.required || undefined\"\n @change=\"onSelect\"\n />\n <span class=\"rp-radio__dot\" />\n <span v-if=\"$slots.default\" class=\"rp-radio__label\">\n <slot />\n </span>\n </label>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useRadio } from './useRadio';\nimport type { RadioProps } from './types';\n\ndefineOptions({ name: 'RpRadio' });\n\nconst props = withDefaults(defineProps<RadioProps>(), {\n variant: undefined,\n color: undefined,\n size: undefined,\n disabled: false,\n});\n\nconst { group, isChecked, isDisabled, rootClass, onSelect } = useRadio(props);\n</script>\n\n<style src=\"./radio.scss\" lang=\"scss\" scoped></style>\n","<template>\n <label\n :class=\"rootClass\"\n :data-disabled=\"isDisabled || undefined\"\n :data-state=\"isChecked ? 'checked' : 'unchecked'\"\n >\n <input\n type=\"radio\"\n class=\"rp-radio__native\"\n :name=\"group.name\"\n :value=\"value\"\n :checked=\"isChecked\"\n :disabled=\"isDisabled || undefined\"\n :required=\"group.required || undefined\"\n @change=\"onSelect\"\n />\n <span class=\"rp-radio__dot\" />\n <span v-if=\"$slots.default\" class=\"rp-radio__label\">\n <slot />\n </span>\n </label>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useRadio } from './useRadio';\nimport type { RadioProps } from './types';\n\ndefineOptions({ name: 'RpRadio' });\n\nconst props = withDefaults(defineProps<RadioProps>(), {\n variant: undefined,\n color: undefined,\n size: undefined,\n disabled: false,\n});\n\nconst { group, isChecked, isDisabled, rootClass, onSelect } = useRadio(props);\n</script>\n\n<style src=\"./radio.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div\n :id=\"control.id\"\n :class=\"rootClass\"\n role=\"radiogroup\"\n :data-disabled=\"control.disabled || undefined\"\n :data-invalid=\"control.invalid || undefined\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n >\n <slot />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useRadioGroup } from './useRadio';\nimport type { RadioGroupProps } from './types';\n\ndefineOptions({ name: 'RpRadioGroup' });\n\nconst props = withDefaults(defineProps<RadioGroupProps>(), {\n variant: undefined,\n color: undefined,\n size: undefined,\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number | null];\n}>();\n\nconst { control, rootClass } = useRadioGroup(props, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./radio-group.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div\n :id=\"control.id\"\n :class=\"rootClass\"\n role=\"radiogroup\"\n :data-disabled=\"control.disabled || undefined\"\n :data-invalid=\"control.invalid || undefined\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n >\n <slot />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useRadioGroup } from './useRadio';\nimport type { RadioGroupProps } from './types';\n\ndefineOptions({ name: 'RpRadioGroup' });\n\nconst props = withDefaults(defineProps<RadioGroupProps>(), {\n variant: undefined,\n color: undefined,\n size: undefined,\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number | null];\n}>();\n\nconst { control, rootClass } = useRadioGroup(props, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./radio-group.scss\" lang=\"scss\" scoped></style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"radio.js","names":[],"sources":["../src/composables/useRequiredInject.ts","../src/components/radio/types.ts","../src/components/radio/useRadio.ts","../src/components/radio/radio.vue","../src/components/radio/radio.vue","../src/components/radio/radio-group.vue","../src/components/radio/radio-group.vue"],"sourcesContent":["import { inject, type InjectionKey } from 'vue';\n\nexport function useRequiredInject<T>(key: InjectionKey<T>, componentName: string): T {\n const value = inject(key);\n if (value == null) {\n throw new Error(\n `[Ropav] <${componentName}> must be used inside its parent provider component.`,\n );\n }\n return value;\n}\n","import type { InjectionKey } from 'vue';\n\nexport type RadioColor =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'info'\n | 'neutral';\n\nexport type RadioSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport type RadioVariant = 'solid' | 'outline';\n\nexport interface RadioProps {\n value: string | number;\n variant?: RadioVariant;\n color?: RadioColor;\n size?: RadioSize;\n disabled?: boolean;\n}\n\nexport interface RadioGroupProps {\n id?: string;\n name?: string;\n modelValue: string | number | null;\n variant?: RadioVariant;\n color?: RadioColor;\n size?: RadioSize;\n disabled?: boolean;\n required?: boolean;\n invalid?: boolean;\n ariaLabel?: string;\n describedby?: string;\n labelledby?: string;\n}\n\nexport interface RadioGroupContext {\n modelValue: string | number | null;\n name: string;\n disabled: boolean;\n required: boolean;\n variant?: RadioVariant;\n color?: RadioColor;\n size?: RadioSize;\n select: (value: string | number) => void;\n}\n\nexport const radioGroupKey = Symbol('radioGroup') as InjectionKey<RadioGroupContext>;\n","import { computed, provide, useId } from 'vue';\nimport { useControlState } from '@/composables/useControlState';\nimport { useRequiredInject } from '@/composables/useRequiredInject';\nimport { bem } from '@/utils/bem';\nimport { radioGroupKey } from './types';\nimport type { RadioGroupContext, RadioGroupProps, RadioProps } from './types';\n\nexport function useRadio(props: Readonly<RadioProps>) {\n const group = useRequiredInject(radioGroupKey, 'RpRadio');\n const isChecked = computed(() => group.modelValue === props.value);\n const isDisabled = computed(() => props.disabled || group.disabled);\n const variant = computed(() => props.variant ?? group.variant);\n const color = computed(() => props.color ?? group.color);\n const size = computed(() => props.size ?? group.size);\n\n const rootClass = computed(() =>\n bem('rp-radio', {\n checked: isChecked.value,\n disabled: isDisabled.value,\n [variant.value ?? '']: Boolean(variant.value),\n [`color-${color.value}`]: Boolean(color.value),\n [`size-${size.value}`]: Boolean(size.value),\n }),\n );\n\n function onSelect() {\n if (isDisabled.value) return;\n group.select(props.value);\n }\n\n return {\n group,\n isChecked,\n isDisabled,\n rootClass,\n onSelect,\n };\n}\n\nexport function useRadioGroup(\n props: Readonly<RadioGroupProps>,\n emitUpdate: (value: string | number | null) => void,\n) {\n const control = useControlState(props);\n\n const rootClass = computed(() =>\n bem('rp-radio-group', {\n disabled: control.disabled,\n invalid: control.invalid,\n }),\n );\n\n const generatedName = useId();\n const groupName = computed(() => props.name ?? `${control.id ?? generatedName}-radio`);\n\n provide<RadioGroupContext>(radioGroupKey, {\n get modelValue() {\n return props.modelValue;\n },\n get name() {\n return groupName.value;\n },\n get disabled() {\n return control.disabled;\n },\n get required() {\n return control.required;\n },\n get variant() {\n return props.variant;\n },\n get color() {\n return props.color;\n },\n get size() {\n return props.size;\n },\n select(value) {\n emitUpdate(value);\n },\n });\n\n return {\n control,\n rootClass,\n };\n}\n","<template>\n <label\n :class=\"rootClass\"\n :data-disabled=\"isDisabled || undefined\"\n :data-state=\"isChecked ? 'checked' : 'unchecked'\"\n >\n <input\n type=\"radio\"\n class=\"rp-radio__native\"\n :name=\"group.name\"\n :value=\"value\"\n :checked=\"isChecked\"\n :disabled=\"isDisabled || undefined\"\n :required=\"group.required || undefined\"\n @change=\"onSelect\"\n />\n <span class=\"rp-radio__dot\" />\n <span v-if=\"$slots.default\" class=\"rp-radio__label\">\n <slot />\n </span>\n </label>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useRadio } from './useRadio';\nimport type { RadioProps } from './types';\n\ndefineOptions({ name: 'RpRadio' });\n\nconst props = withDefaults(defineProps<RadioProps>(), {\n variant: undefined,\n color: undefined,\n size: undefined,\n disabled: false,\n});\n\nconst { group, isChecked, isDisabled, rootClass, onSelect } = useRadio(props);\n</script>\n\n<style src=\"./radio.scss\" lang=\"scss\" scoped></style>\n","<template>\n <label\n :class=\"rootClass\"\n :data-disabled=\"isDisabled || undefined\"\n :data-state=\"isChecked ? 'checked' : 'unchecked'\"\n >\n <input\n type=\"radio\"\n class=\"rp-radio__native\"\n :name=\"group.name\"\n :value=\"value\"\n :checked=\"isChecked\"\n :disabled=\"isDisabled || undefined\"\n :required=\"group.required || undefined\"\n @change=\"onSelect\"\n />\n <span class=\"rp-radio__dot\" />\n <span v-if=\"$slots.default\" class=\"rp-radio__label\">\n <slot />\n </span>\n </label>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useRadio } from './useRadio';\nimport type { RadioProps } from './types';\n\ndefineOptions({ name: 'RpRadio' });\n\nconst props = withDefaults(defineProps<RadioProps>(), {\n variant: undefined,\n color: undefined,\n size: undefined,\n disabled: false,\n});\n\nconst { group, isChecked, isDisabled, rootClass, onSelect } = useRadio(props);\n</script>\n\n<style src=\"./radio.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div\n :id=\"control.id\"\n :class=\"rootClass\"\n role=\"radiogroup\"\n :data-disabled=\"control.disabled || undefined\"\n :data-invalid=\"control.invalid || undefined\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n >\n <slot />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useRadioGroup } from './useRadio';\nimport type { RadioGroupProps } from './types';\n\ndefineOptions({ name: 'RpRadioGroup' });\n\nconst props = withDefaults(defineProps<RadioGroupProps>(), {\n variant: undefined,\n color: undefined,\n size: undefined,\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number | null];\n}>();\n\nconst { control, rootClass } = useRadioGroup(props, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./radio-group.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div\n :id=\"control.id\"\n :class=\"rootClass\"\n role=\"radiogroup\"\n :data-disabled=\"control.disabled || undefined\"\n :data-invalid=\"control.invalid || undefined\"\n :aria-label=\"ariaLabel || undefined\"\n :aria-labelledby=\"control.ariaLabelledby\"\n :aria-describedby=\"control.ariaDescribedby\"\n :aria-invalid=\"control.invalid || undefined\"\n :aria-required=\"control.required || undefined\"\n >\n <slot />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useRadioGroup } from './useRadio';\nimport type { RadioGroupProps } from './types';\n\ndefineOptions({ name: 'RpRadioGroup' });\n\nconst props = withDefaults(defineProps<RadioGroupProps>(), {\n variant: undefined,\n color: undefined,\n size: undefined,\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number | null];\n}>();\n\nconst { control, rootClass } = useRadioGroup(props, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./radio-group.scss\" lang=\"scss\" scoped></style>\n"],"mappings":"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"}
|
package/dist/select.css
CHANGED
|
@@ -20,19 +20,19 @@
|
|
|
20
20
|
height: var(--rp-size-control-md);
|
|
21
21
|
padding: 0 var(--rp-spacing-3);
|
|
22
22
|
font-size: var(--rp-font-size-base);
|
|
23
|
-
background-color: var(--rp-color-
|
|
24
|
-
border: var(--rp-border-width-thin) solid var(--rp-color-border);
|
|
23
|
+
background-color: var(--rp-color-control-bg);
|
|
24
|
+
border: var(--rp-border-width-thin) solid var(--rp-color-control-border);
|
|
25
25
|
border-radius: var(--_rp-select-radius);
|
|
26
26
|
cursor: pointer;
|
|
27
27
|
transition: border-color var(--rp-transition-fast), box-shadow var(--rp-transition-fast);
|
|
28
28
|
gap: var(--rp-spacing-2);
|
|
29
29
|
}
|
|
30
30
|
.rp-select__trigger[data-v-9838513c]:hover {
|
|
31
|
-
border-color: var(--rp-color-border-hover);
|
|
31
|
+
border-color: var(--rp-color-control-border-hover);
|
|
32
32
|
}
|
|
33
33
|
.rp-select__trigger[data-v-9838513c]:focus-visible {
|
|
34
34
|
outline: none;
|
|
35
|
-
border-color: var(--rp-color-
|
|
35
|
+
border-color: var(--rp-color-control-border-focus);
|
|
36
36
|
box-shadow: 0 0 0 var(--rp-border-width-medium) var(--rp-color-focus-ring);
|
|
37
37
|
}
|
|
38
38
|
.rp-select--radius-xs[data-v-9838513c] {
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
--_rp-select-radius: var(--rp-radius-xl);
|
|
52
52
|
}
|
|
53
53
|
.rp-select--open .rp-select__trigger[data-v-9838513c] {
|
|
54
|
-
border-color: var(--rp-color-
|
|
54
|
+
border-color: var(--rp-color-control-border-focus);
|
|
55
55
|
box-shadow: 0 0 0 var(--rp-border-width-medium) var(--rp-color-focus-ring);
|
|
56
56
|
}
|
|
57
57
|
.rp-select--invalid .rp-select__trigger[data-v-9838513c] {
|
|
@@ -62,10 +62,10 @@
|
|
|
62
62
|
overflow: hidden;
|
|
63
63
|
text-overflow: ellipsis;
|
|
64
64
|
white-space: nowrap;
|
|
65
|
-
color: var(--rp-color-
|
|
65
|
+
color: var(--rp-color-control-fg);
|
|
66
66
|
}
|
|
67
67
|
.rp-select__placeholder[data-v-9838513c] {
|
|
68
|
-
color: var(--rp-color-
|
|
68
|
+
color: var(--rp-color-control-placeholder);
|
|
69
69
|
}
|
|
70
70
|
.rp-select__indicator[data-v-9838513c] {
|
|
71
71
|
display: inline-flex;
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
}
|
|
81
81
|
.rp-select__indicator[data-v-9838513c] {
|
|
82
82
|
position: relative;
|
|
83
|
-
color: var(--rp-color-
|
|
83
|
+
color: var(--rp-color-control-icon);
|
|
84
84
|
transform: translateX(var(--rp-spacing-1));
|
|
85
85
|
}
|
|
86
86
|
.rp-select__arrow[data-v-9838513c] {
|
|
@@ -117,13 +117,13 @@
|
|
|
117
117
|
position: absolute;
|
|
118
118
|
inset: 0;
|
|
119
119
|
z-index: 1;
|
|
120
|
-
color: var(--rp-color-
|
|
120
|
+
color: var(--rp-color-control-icon);
|
|
121
121
|
opacity: 0;
|
|
122
122
|
pointer-events: none;
|
|
123
123
|
transition: color var(--rp-transition-fast), opacity var(--rp-transition-fast);
|
|
124
124
|
}
|
|
125
125
|
.rp-select__clear[data-v-9838513c]:hover {
|
|
126
|
-
color: var(--rp-color-
|
|
126
|
+
color: var(--rp-color-control-fg);
|
|
127
127
|
}
|
|
128
128
|
.rp-select__trigger:hover .rp-select__clear[data-v-9838513c] {
|
|
129
129
|
opacity: 1;
|
|
@@ -155,7 +155,7 @@
|
|
|
155
155
|
font-size: var(--rp-font-size-base);
|
|
156
156
|
cursor: pointer;
|
|
157
157
|
transition: background-color var(--rp-transition-fast), color var(--rp-transition-fast);
|
|
158
|
-
color: var(--rp-color-
|
|
158
|
+
color: var(--rp-color-control-fg);
|
|
159
159
|
}
|
|
160
160
|
.rp-select__option--focused[data-v-9838513c] {
|
|
161
161
|
background-color: var(--rp-color-surface-hover);
|
package/dist/select.js
CHANGED
|
@@ -1,48 +1,26 @@
|
|
|
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,
|
|
4
|
+
import { VaporTransition, child, computed, createComponent, createFor, createIf, createInvoker, createSelector, createSlot, createTemplateRefSetter, defineVaporComponent, delegateEvents, extend, markRaw, next, nextTick, on, onBeforeUnmount, onMounted, ref, renderEffect, setAttr, setClass, setClassName, setInsertionState, setProp, setText, setValue, template, toDisplayString, txt, unref, useId, watch, withModifiers, withVaporModifiers } from "vue";
|
|
5
5
|
//#region ~icons/lucide/chevrons-up-down
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
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)])]);
|
|
6
|
+
var t0$2 = template("<svg viewBox=\"0 0 24 24\"width=1.2em height=1.2em><path fill=none stroke=currentColor stroke-linecap=round stroke-linejoin=round stroke-width=2 d=\"m7 15l5 5l5-5M7 9l5-5l5 5\">", 3, 1);
|
|
7
|
+
function render$1(_ctx) {
|
|
8
|
+
return t0$2();
|
|
20
9
|
}
|
|
21
|
-
var chevrons_up_down_default = markRaw({
|
|
10
|
+
var chevrons_up_down_default = markRaw(defineVaporComponent({
|
|
22
11
|
name: "lucide-chevrons-up-down",
|
|
23
12
|
render: render$1
|
|
24
|
-
});
|
|
13
|
+
}));
|
|
25
14
|
//#endregion
|
|
26
15
|
//#region ~icons/lucide/x
|
|
27
|
-
var
|
|
28
|
-
|
|
29
|
-
|
|
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)])]);
|
|
16
|
+
var t0$1 = template("<svg viewBox=\"0 0 24 24\"width=1.2em height=1.2em><path fill=none stroke=currentColor stroke-linecap=round stroke-linejoin=round stroke-width=2 d=\"M18 6L6 18M6 6l12 12\">", 3, 1);
|
|
17
|
+
function render(_ctx) {
|
|
18
|
+
return t0$1();
|
|
41
19
|
}
|
|
42
|
-
var x_default = markRaw({
|
|
20
|
+
var x_default = markRaw(defineVaporComponent({
|
|
43
21
|
name: "lucide-x",
|
|
44
22
|
render
|
|
45
|
-
});
|
|
23
|
+
}));
|
|
46
24
|
//#endregion
|
|
47
25
|
//#region src/composables/useClickOutside.ts
|
|
48
26
|
function useClickOutside(target, active, callback) {
|
package/dist/select.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
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,12 +1,12 @@
|
|
|
1
1
|
.rp-switch[data-v-aeef0d94] {
|
|
2
|
-
--_switch-color: var(--rp-color-
|
|
2
|
+
--_switch-color: var(--rp-color-control-selected-bg);
|
|
3
3
|
--_switch-font-size: var(--rp-font-size-base);
|
|
4
4
|
--_track-w: 40px;
|
|
5
5
|
--_track-h: 22px;
|
|
6
6
|
--_thumb-size: 18px;
|
|
7
7
|
--_thumb-offset: 2px;
|
|
8
|
-
--_track-bg: var(--rp-color-
|
|
9
|
-
--_thumb-bg:
|
|
8
|
+
--_track-bg: var(--rp-color-control-track-bg);
|
|
9
|
+
--_thumb-bg: var(--rp-color-control-thumb-bg);
|
|
10
10
|
display: inline-flex;
|
|
11
11
|
align-items: center;
|
|
12
12
|
cursor: pointer;
|
|
@@ -21,9 +21,6 @@
|
|
|
21
21
|
gap: var(--rp-spacing-2);
|
|
22
22
|
font-size: var(--_switch-font-size);
|
|
23
23
|
}
|
|
24
|
-
html.dark .rp-switch[data-v-aeef0d94] {
|
|
25
|
-
--_thumb-bg: var(--rp-color-surface-inverted);
|
|
26
|
-
}
|
|
27
24
|
.rp-switch__native[data-v-aeef0d94] {
|
|
28
25
|
position: absolute;
|
|
29
26
|
width: 1px;
|
|
@@ -93,6 +90,9 @@ html.dark .rp-switch[data-v-aeef0d94] {
|
|
|
93
90
|
.rp-switch--color-info[data-v-aeef0d94] {
|
|
94
91
|
--_switch-color: var(--rp-color-info);
|
|
95
92
|
}
|
|
93
|
+
.rp-switch--color-neutral[data-v-aeef0d94] {
|
|
94
|
+
--_switch-color: var(--rp-color-neutral);
|
|
95
|
+
}
|
|
96
96
|
.rp-switch--size-xs[data-v-aeef0d94] {
|
|
97
97
|
--_track-w: 28px;
|
|
98
98
|
--_track-h: 16px;
|
package/dist/textarea.css
CHANGED
|
@@ -3,20 +3,24 @@
|
|
|
3
3
|
--_rp-textarea-padding-x: var(--rp-spacing-3);
|
|
4
4
|
--_rp-textarea-font-size: var(--rp-font-size-base);
|
|
5
5
|
--_rp-textarea-radius: var(--rp-radius-sm);
|
|
6
|
+
--_rp-textarea-valid-border: var(--rp-color-success-border-hover);
|
|
7
|
+
--_rp-textarea-valid-ring: color-mix(in srgb, var(--rp-color-success) 32%, transparent);
|
|
8
|
+
--_rp-textarea-invalid-border: var(--rp-color-danger-border-hover);
|
|
9
|
+
--_rp-textarea-invalid-ring: color-mix(in srgb, var(--rp-color-danger) 32%, transparent);
|
|
6
10
|
display: inline-flex;
|
|
7
11
|
box-sizing: border-box;
|
|
8
12
|
font-family: var(--rp-font-family);
|
|
9
13
|
font-weight: var(--rp-font-weight-normal);
|
|
10
|
-
background-color: var(--rp-color-
|
|
11
|
-
border: var(--rp-border-width-thin) solid var(--rp-color-border);
|
|
14
|
+
background-color: var(--rp-color-control-bg);
|
|
15
|
+
border: var(--rp-border-width-thin) solid var(--rp-color-control-border);
|
|
12
16
|
cursor: text;
|
|
13
17
|
transition: border-color var(--rp-transition-fast), box-shadow var(--rp-transition-fast);
|
|
14
18
|
}
|
|
15
19
|
.rp-textarea[data-v-2c68871d]:hover:not(.rp-textarea--disabled):not(.rp-textarea--invalid):not(.rp-textarea--valid) {
|
|
16
|
-
border-color: var(--rp-color-border-hover);
|
|
20
|
+
border-color: var(--rp-color-control-border-hover);
|
|
17
21
|
}
|
|
18
22
|
.rp-textarea[data-v-2c68871d]:focus-within:not(.rp-textarea--disabled):not(.rp-textarea--invalid):not(.rp-textarea--valid) {
|
|
19
|
-
border-color: var(--rp-color-
|
|
23
|
+
border-color: var(--rp-color-control-border-focus);
|
|
20
24
|
box-shadow: 0 0 0 var(--rp-border-width-medium) var(--rp-color-focus-ring);
|
|
21
25
|
}
|
|
22
26
|
.rp-textarea[data-v-2c68871d] {
|
|
@@ -64,26 +68,32 @@
|
|
|
64
68
|
.rp-textarea--radius-xl[data-v-2c68871d] {
|
|
65
69
|
--_rp-textarea-radius: var(--rp-radius-xl);
|
|
66
70
|
}
|
|
71
|
+
html.dark .rp-textarea[data-v-2c68871d] {
|
|
72
|
+
--_rp-textarea-valid-border: var(--rp-color-success-fg);
|
|
73
|
+
--_rp-textarea-valid-ring: color-mix(in srgb, var(--rp-color-success-fg) 32%, transparent);
|
|
74
|
+
--_rp-textarea-invalid-border: var(--rp-color-danger-fg);
|
|
75
|
+
--_rp-textarea-invalid-ring: color-mix(in srgb, var(--rp-color-danger-fg) 32%, transparent);
|
|
76
|
+
}
|
|
67
77
|
.rp-textarea--disabled[data-v-2c68871d] {
|
|
68
78
|
opacity: var(--rp-opacity-disabled);
|
|
69
79
|
cursor: not-allowed;
|
|
70
80
|
}
|
|
71
81
|
.rp-textarea--valid[data-v-2c68871d] {
|
|
72
|
-
border-color: var(--
|
|
82
|
+
border-color: var(--_rp-textarea-valid-border);
|
|
73
83
|
}
|
|
74
84
|
.rp-textarea--valid[data-v-2c68871d]:focus-within:not(.rp-textarea--disabled) {
|
|
75
|
-
border-color: var(--
|
|
76
|
-
box-shadow: 0 0 0 var(--rp-border-width-medium)
|
|
85
|
+
border-color: var(--_rp-textarea-valid-border);
|
|
86
|
+
box-shadow: 0 0 0 var(--rp-border-width-medium) var(--_rp-textarea-valid-ring);
|
|
77
87
|
}
|
|
78
88
|
.rp-textarea--invalid[data-v-2c68871d] {
|
|
79
|
-
border-color: var(--
|
|
89
|
+
border-color: var(--_rp-textarea-invalid-border);
|
|
80
90
|
}
|
|
81
91
|
.rp-textarea--invalid[data-v-2c68871d]:focus-within:not(.rp-textarea--disabled) {
|
|
82
|
-
border-color: var(--
|
|
83
|
-
box-shadow: 0 0 0 var(--rp-border-width-medium)
|
|
92
|
+
border-color: var(--_rp-textarea-invalid-border);
|
|
93
|
+
box-shadow: 0 0 0 var(--rp-border-width-medium) var(--_rp-textarea-invalid-ring);
|
|
84
94
|
}
|
|
85
95
|
.rp-textarea--readonly[data-v-2c68871d] {
|
|
86
|
-
background-color: var(--rp-color-
|
|
96
|
+
background-color: var(--rp-color-control-readonly-bg);
|
|
87
97
|
}
|
|
88
98
|
.rp-textarea__native[data-v-2c68871d] {
|
|
89
99
|
box-sizing: border-box;
|
|
@@ -95,11 +105,11 @@
|
|
|
95
105
|
outline: none;
|
|
96
106
|
background: transparent;
|
|
97
107
|
font: inherit;
|
|
98
|
-
color: var(--rp-color-
|
|
108
|
+
color: var(--rp-color-control-fg);
|
|
99
109
|
line-height: var(--rp-line-height-relaxed);
|
|
100
110
|
}
|
|
101
111
|
.rp-textarea__native[data-v-2c68871d]::placeholder {
|
|
102
|
-
color: var(--rp-color-
|
|
112
|
+
color: var(--rp-color-control-placeholder);
|
|
103
113
|
}
|
|
104
114
|
.rp-textarea__native[data-v-2c68871d]:disabled {
|
|
105
115
|
cursor: not-allowed;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ropav",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"packageManager": "pnpm@11.9.0",
|
|
6
6
|
"engines": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"dev": "pnpm run storybook",
|
|
57
57
|
"tokens:build": "style-dictionary build --config scripts/tokens.config.mjs --silent",
|
|
58
58
|
"tokens:check": "node scripts/check-tokens.mjs",
|
|
59
|
-
"typecheck": "vue-tsc -b tsconfig.app.json tsconfig.node.json",
|
|
59
|
+
"typecheck": "vue-tsc -b tsconfig.app.json tsconfig.node.json tsconfig.test.json",
|
|
60
60
|
"typecheck:storybook": "vue-tsc -p tsconfig.storybook.json --noEmit",
|
|
61
61
|
"lint": "oxlint",
|
|
62
62
|
"lint:fix": "oxlint --fix",
|
|
@@ -86,6 +86,7 @@
|
|
|
86
86
|
"@types/node": "^25.9.4",
|
|
87
87
|
"@vitejs/plugin-vue": "^6.0.7",
|
|
88
88
|
"@vitest/browser-playwright": "^4.1.9",
|
|
89
|
+
"@vue/compiler-vapor": "3.6.0-beta.17",
|
|
89
90
|
"@vue/tsconfig": "^0.9.1",
|
|
90
91
|
"bumpp": "^11.1.0",
|
|
91
92
|
"jsdom": "^29.1.1",
|
package/src/styles/_mixins.scss
CHANGED
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
@mixin semantic-colors($var-name) {
|
|
107
|
-
@each $name in primary, secondary, success, warning, danger, info {
|
|
107
|
+
@each $name in primary, secondary, success, warning, danger, info, neutral {
|
|
108
108
|
&--#{$name} {
|
|
109
109
|
#{$var-name}: var(--rp-color-#{$name}-fg);
|
|
110
110
|
}
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
@mixin semantic-color-pair($color-var, $foreground-var) {
|
|
115
|
-
@each $name in primary, secondary, success, warning, danger, info {
|
|
115
|
+
@each $name in primary, secondary, success, warning, danger, info, neutral {
|
|
116
116
|
&--#{$name} {
|
|
117
117
|
#{$color-var}: var(--rp-color-#{$name});
|
|
118
118
|
#{$foreground-var}: var(--rp-color-on-#{$name});
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
@mixin semantic-state-colors($prefix) {
|
|
124
|
-
@each $name in primary, secondary, success, warning, danger, info {
|
|
124
|
+
@each $name in primary, secondary, success, warning, danger, info, neutral {
|
|
125
125
|
&--#{$name} {
|
|
126
126
|
#{$prefix}-bg: var(--rp-color-#{$name});
|
|
127
127
|
#{$prefix}-bg-hover: var(--rp-color-#{$name}-hover);
|
package/src/styles/_tokens.scss
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
--rp-color-warning : #{$color-warning};
|
|
15
15
|
--rp-color-danger : #{$color-danger};
|
|
16
16
|
--rp-color-info : #{$color-info};
|
|
17
|
+
--rp-color-neutral : #{$color-neutral};
|
|
17
18
|
--rp-color-text : #{$color-text};
|
|
18
19
|
--rp-color-text-secondary : #{$color-text-secondary};
|
|
19
20
|
--rp-color-text-disabled : #{$color-text-disabled};
|
|
@@ -31,12 +32,25 @@
|
|
|
31
32
|
--rp-color-border : #{$color-border};
|
|
32
33
|
--rp-color-border-hover : #{$color-border-hover};
|
|
33
34
|
--rp-color-focus-ring : color-mix(in srgb, var(--rp-color-primary) 32%, transparent);
|
|
35
|
+
--rp-color-control-bg : #{$color-gray-2};
|
|
36
|
+
--rp-color-control-readonly-bg : var(--rp-color-surface-muted);
|
|
37
|
+
--rp-color-control-fg : var(--rp-color-text);
|
|
38
|
+
--rp-color-control-placeholder : var(--rp-color-text-secondary);
|
|
39
|
+
--rp-color-control-icon : var(--rp-color-text-secondary);
|
|
40
|
+
--rp-color-control-border : var(--rp-color-border);
|
|
41
|
+
--rp-color-control-border-hover : var(--rp-color-border-hover);
|
|
42
|
+
--rp-color-control-border-focus : var(--rp-color-primary);
|
|
43
|
+
--rp-color-control-track-bg : var(--rp-color-border);
|
|
44
|
+
--rp-color-control-thumb-bg : #{$color-white};
|
|
45
|
+
--rp-color-control-selected-bg : var(--rp-color-primary);
|
|
46
|
+
--rp-color-control-selected-fg : var(--rp-color-on-primary);
|
|
34
47
|
--rp-color-on-primary : #{$color-on-primary};
|
|
35
48
|
--rp-color-on-secondary : #{$color-on-secondary};
|
|
36
49
|
--rp-color-on-success : #{$color-on-success};
|
|
37
50
|
--rp-color-on-warning : #{$color-on-warning};
|
|
38
51
|
--rp-color-on-danger : #{$color-on-danger};
|
|
39
52
|
--rp-color-on-info : #{$color-on-info};
|
|
53
|
+
--rp-color-on-neutral : #{$color-on-neutral};
|
|
40
54
|
--rp-color-primary-hover : color-mix(in srgb, var(--rp-color-primary) 90%, #{$color-black});
|
|
41
55
|
--rp-color-primary-active : color-mix(in srgb, var(--rp-color-primary) 80%, #{$color-black});
|
|
42
56
|
--rp-color-primary-subtle-bg : #e6f4fe;
|
|
@@ -85,6 +99,14 @@
|
|
|
85
99
|
--rp-color-info-border : #7dcedc;
|
|
86
100
|
--rp-color-info-border-hover : #3db9cf;
|
|
87
101
|
--rp-color-info-fg : #0d3c48;
|
|
102
|
+
--rp-color-neutral-hover : color-mix(in srgb, var(--rp-color-neutral) 90%, #{$color-black});
|
|
103
|
+
--rp-color-neutral-active : color-mix(in srgb, var(--rp-color-neutral) 80%, #{$color-black});
|
|
104
|
+
--rp-color-neutral-subtle-bg : #f0f0f0;
|
|
105
|
+
--rp-color-neutral-subtle-bg-hover : #e8e8e8;
|
|
106
|
+
--rp-color-neutral-subtle-bg-active : #e0e0e0;
|
|
107
|
+
--rp-color-neutral-border : #cecece;
|
|
108
|
+
--rp-color-neutral-border-hover : #bbbbbb;
|
|
109
|
+
--rp-color-neutral-fg : #202020;
|
|
88
110
|
|
|
89
111
|
// Font sizes
|
|
90
112
|
--rp-font-size-xs : #{$font-size-xs};
|
|
@@ -137,6 +159,9 @@
|
|
|
137
159
|
--rp-size-control-md: #{$size-control-md};
|
|
138
160
|
--rp-size-control-lg: #{$size-control-lg};
|
|
139
161
|
|
|
162
|
+
// Opacity
|
|
163
|
+
--rp-opacity-disabled: #{$opacity-disabled};
|
|
164
|
+
|
|
140
165
|
// Shadows
|
|
141
166
|
--rp-shadow-sm : #{$shadow-sm};
|
|
142
167
|
--rp-shadow-base: #{$shadow-base};
|
|
@@ -169,6 +194,16 @@ html.dark {
|
|
|
169
194
|
--rp-color-border : #3a3a3a;
|
|
170
195
|
--rp-color-border-hover : #606060;
|
|
171
196
|
--rp-color-focus-ring : color-mix(in srgb, var(--rp-color-primary) 45%, transparent);
|
|
197
|
+
--rp-color-control-bg : #191919;
|
|
198
|
+
--rp-color-control-readonly-bg : var(--rp-color-surface-muted);
|
|
199
|
+
--rp-color-control-fg : #eeeeee;
|
|
200
|
+
--rp-color-control-placeholder : #6e6e6e;
|
|
201
|
+
--rp-color-control-icon : #b4b4b4;
|
|
202
|
+
--rp-color-control-border : #3a3a3a;
|
|
203
|
+
--rp-color-control-border-hover : #606060;
|
|
204
|
+
--rp-color-control-border-focus : var(--rp-color-primary);
|
|
205
|
+
--rp-color-control-track-bg : var(--rp-color-border);
|
|
206
|
+
--rp-color-control-thumb-bg : var(--rp-color-surface-inverted);
|
|
172
207
|
--rp-color-primary-subtle-bg : #0d2847;
|
|
173
208
|
--rp-color-primary-subtle-bg-hover : #003362;
|
|
174
209
|
--rp-color-primary-subtle-bg-active : #004074;
|
|
@@ -205,6 +240,12 @@ html.dark {
|
|
|
205
240
|
--rp-color-info-border : #12677e;
|
|
206
241
|
--rp-color-info-border-hover : #11809c;
|
|
207
242
|
--rp-color-info-fg : #4ccce6;
|
|
243
|
+
--rp-color-neutral-subtle-bg : #222222;
|
|
244
|
+
--rp-color-neutral-subtle-bg-hover : #2a2a2a;
|
|
245
|
+
--rp-color-neutral-subtle-bg-active : #313131;
|
|
246
|
+
--rp-color-neutral-border : #484848;
|
|
247
|
+
--rp-color-neutral-border-hover : #606060;
|
|
248
|
+
--rp-color-neutral-fg : #eeeeee;
|
|
208
249
|
|
|
209
250
|
// Shadows
|
|
210
251
|
--rp-shadow-sm : 0 1px 2px 0 rgba(0, 0, 0, 0.3);
|
|
@@ -11,6 +11,7 @@ $color-success : #218358 !default;
|
|
|
11
11
|
$color-warning : #cc4e00 !default;
|
|
12
12
|
$color-danger : #ce2c31 !default;
|
|
13
13
|
$color-info : #107d98 !default;
|
|
14
|
+
$color-neutral : #646464 !default;
|
|
14
15
|
$color-white : #ffffff !default;
|
|
15
16
|
$color-black : #111111 !default;
|
|
16
17
|
$color-gray-1 : #fcfcfc !default;
|
|
@@ -37,6 +38,7 @@ $color-on-success : $color-white !default;
|
|
|
37
38
|
$color-on-warning : $color-white !default;
|
|
38
39
|
$color-on-danger : $color-white !default;
|
|
39
40
|
$color-on-info : $color-white !default;
|
|
41
|
+
$color-on-neutral : $color-white !default;
|
|
40
42
|
|
|
41
43
|
// Font sizes
|
|
42
44
|
$font-size-xs : 0.75rem !default;
|