ropav 0.0.2
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/README.md +31 -0
- package/dist/_plugin-vue_export-helper.js +18 -0
- package/dist/_plugin-vue_export-helper.js.map +1 -0
- package/dist/base.css +147 -0
- package/dist/button.css +66 -0
- package/dist/button.js +62 -0
- package/dist/button.js.map +1 -0
- package/dist/checkbox.css +60 -0
- package/dist/checkbox.js +132 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/components/_internal/icons/CheckIcon.d.ts +18 -0
- package/dist/components/_internal/icons/ChevronDownIcon.d.ts +18 -0
- package/dist/components/_internal/icons/MinusIcon.d.ts +18 -0
- package/dist/components/_internal/icons/index.d.ts +3 -0
- package/dist/components/_internal/optionList.d.ts +9 -0
- package/dist/components/button/button.d.ts +25 -0
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/button/index.js +2 -0
- package/dist/components/button/types.d.ts +6 -0
- package/dist/components/checkbox/checkbox.d.ts +23 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/checkbox/index.js +2 -0
- package/dist/components/checkbox/types.d.ts +12 -0
- package/dist/components/checkbox/useCheckbox.d.ts +6 -0
- package/dist/components/input/index.d.ts +2 -0
- package/dist/components/input/index.js +2 -0
- package/dist/components/input/input.d.ts +21 -0
- package/dist/components/input/types.d.ts +14 -0
- package/dist/components/radio/index.d.ts +3 -0
- package/dist/components/radio/index.js +2 -0
- package/dist/components/radio/radio-group.d.ts +23 -0
- package/dist/components/radio/radio.d.ts +21 -0
- package/dist/components/radio/types.d.ts +24 -0
- package/dist/components/radio/useRadio.d.ts +12 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +2 -0
- package/dist/components/select/select.d.ts +23 -0
- package/dist/components/select/types.d.ts +18 -0
- package/dist/components/select/useSelect.d.ts +21 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/switch/index.js +2 -0
- package/dist/components/switch/switch.d.ts +23 -0
- package/dist/components/switch/types.d.ts +11 -0
- package/dist/components/switch/useSwitch.d.ts +6 -0
- package/dist/components/tabs/index.d.ts +5 -0
- package/dist/components/tabs/index.js +2 -0
- package/dist/components/tabs/tab-panel.d.ts +21 -0
- package/dist/components/tabs/tabs-list.d.ts +20 -0
- package/dist/components/tabs/tabs-trigger.d.ts +21 -0
- package/dist/components/tabs/tabs.d.ts +23 -0
- package/dist/components/tabs/types.d.ts +18 -0
- package/dist/components/tabs/useTabs.d.ts +19 -0
- package/dist/components/textarea/index.d.ts +2 -0
- package/dist/components/textarea/index.js +2 -0
- package/dist/components/textarea/textarea.d.ts +21 -0
- package/dist/components/textarea/types.d.ts +14 -0
- package/dist/components/textarea/useTextarea.d.ts +6 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +2 -0
- package/dist/components/tooltip/tooltip.d.ts +23 -0
- package/dist/components/tooltip/types.d.ts +5 -0
- package/dist/components/tooltip/useTooltip.d.ts +8 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +10 -0
- package/dist/input.css +51 -0
- package/dist/input.js +79 -0
- package/dist/input.js.map +1 -0
- package/dist/radio.css +66 -0
- package/dist/radio.js +160 -0
- package/dist/radio.js.map +1 -0
- package/dist/select.css +122 -0
- package/dist/select.js +362 -0
- package/dist/select.js.map +1 -0
- package/dist/switch.css +70 -0
- package/dist/switch.js +94 -0
- package/dist/switch.js.map +1 -0
- package/dist/tabs.css +45 -0
- package/dist/tabs.js +205 -0
- package/dist/tabs.js.map +1 -0
- package/dist/textarea.css +46 -0
- package/dist/textarea.js +91 -0
- package/dist/textarea.js.map +1 -0
- package/dist/tooltip.css +78 -0
- package/dist/tooltip.js +112 -0
- package/dist/tooltip.js.map +1 -0
- package/dist/useControlState.js +38 -0
- package/dist/useControlState.js.map +1 -0
- package/dist/useRequiredInject.js +11 -0
- package/dist/useRequiredInject.js.map +1 -0
- package/package.json +110 -0
- package/src/styles/_mixins.scss +128 -0
- package/src/styles/_tokens.scss +184 -0
- package/src/styles/_variables.scss +112 -0
- package/src/styles/base.scss +1 -0
package/dist/tabs.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import './tabs.css';
|
|
2
|
+
import { n as bem, t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper.js";
|
|
3
|
+
import { t as useRequiredInject } from "./useRequiredInject.js";
|
|
4
|
+
import { computed, createIf, createInvoker, createSlot, createTemplateRefSetter, defineVaporComponent, delegateEvents, provide, ref, renderEffect, setAttr, setClass, setInsertionState, setProp, template, unref, useId } from "vue";
|
|
5
|
+
//#region src/components/tabs/types.ts
|
|
6
|
+
var tabsKey = Symbol("tabs");
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/components/tabs/useTabs.ts
|
|
9
|
+
function safeTabId(value) {
|
|
10
|
+
return value.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
11
|
+
}
|
|
12
|
+
function useTabs(props, tabsId, emitUpdate) {
|
|
13
|
+
function select(value) {
|
|
14
|
+
emitUpdate(value);
|
|
15
|
+
}
|
|
16
|
+
function getTriggerId(value) {
|
|
17
|
+
return `${tabsId}-trigger-${safeTabId(value)}`;
|
|
18
|
+
}
|
|
19
|
+
function getPanelId(value) {
|
|
20
|
+
return `${tabsId}-panel-${safeTabId(value)}`;
|
|
21
|
+
}
|
|
22
|
+
const rootClass = computed(() => bem("rp-tabs"));
|
|
23
|
+
provide(tabsKey, {
|
|
24
|
+
get activeTab() {
|
|
25
|
+
return props.modelValue;
|
|
26
|
+
},
|
|
27
|
+
select,
|
|
28
|
+
getTriggerId,
|
|
29
|
+
getPanelId
|
|
30
|
+
});
|
|
31
|
+
return { rootClass };
|
|
32
|
+
}
|
|
33
|
+
function getEnabledTabs(list) {
|
|
34
|
+
if (!list) return [];
|
|
35
|
+
return Array.from(list.querySelectorAll("[role=\"tab\"]")).filter((tab) => !tab.disabled && tab.getAttribute("aria-disabled") !== "true");
|
|
36
|
+
}
|
|
37
|
+
function useTabsList() {
|
|
38
|
+
const tabs = useRequiredInject(tabsKey, "RpTabsList");
|
|
39
|
+
const listRef = ref(null);
|
|
40
|
+
const rootClass = computed(() => bem("rp-tabs__list"));
|
|
41
|
+
function focusTab(index) {
|
|
42
|
+
const items = getEnabledTabs(listRef.value);
|
|
43
|
+
if (items.length === 0) return;
|
|
44
|
+
const item = items[(index + items.length) % items.length];
|
|
45
|
+
item.focus();
|
|
46
|
+
const value = item.dataset.value;
|
|
47
|
+
if (value) tabs.select(value);
|
|
48
|
+
}
|
|
49
|
+
function onKeydown(e) {
|
|
50
|
+
if (![
|
|
51
|
+
"ArrowRight",
|
|
52
|
+
"ArrowDown",
|
|
53
|
+
"ArrowLeft",
|
|
54
|
+
"ArrowUp",
|
|
55
|
+
"Home",
|
|
56
|
+
"End"
|
|
57
|
+
].includes(e.key)) return;
|
|
58
|
+
const items = getEnabledTabs(listRef.value);
|
|
59
|
+
if (items.length === 0) return;
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
const current = items.indexOf(document.activeElement);
|
|
62
|
+
if (e.key === "Home") focusTab(0);
|
|
63
|
+
else if (e.key === "End") focusTab(items.length - 1);
|
|
64
|
+
else if (e.key === "ArrowRight" || e.key === "ArrowDown") focusTab(current + 1);
|
|
65
|
+
else focusTab(current - 1);
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
listRef,
|
|
69
|
+
rootClass,
|
|
70
|
+
onKeydown
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function useTabsTrigger(props) {
|
|
74
|
+
const tabs = useRequiredInject(tabsKey, "RpTabsTrigger");
|
|
75
|
+
const isActive = computed(() => tabs.activeTab === props.value);
|
|
76
|
+
const rootClass = computed(() => bem("rp-tabs__trigger", {
|
|
77
|
+
active: isActive.value,
|
|
78
|
+
disabled: props.disabled
|
|
79
|
+
}));
|
|
80
|
+
function select() {
|
|
81
|
+
if (!props.disabled) tabs.select(props.value);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
tabs,
|
|
85
|
+
isActive,
|
|
86
|
+
rootClass,
|
|
87
|
+
select
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function useTabPanel(props) {
|
|
91
|
+
const tabs = useRequiredInject(tabsKey, "RpTabPanel");
|
|
92
|
+
return {
|
|
93
|
+
tabs,
|
|
94
|
+
isActive: computed(() => tabs.activeTab === props.value)
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/components/tabs/tabs.vue?vue&type=script&setup=true&vapor=true&lang.ts
|
|
99
|
+
var t0$3 = template("<div data-v-f9df84ad>", 1);
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/components/tabs/tabs.vue
|
|
102
|
+
var tabs_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineVaporComponent({
|
|
103
|
+
name: "RpTabs",
|
|
104
|
+
__name: "tabs",
|
|
105
|
+
props: { modelValue: {} },
|
|
106
|
+
emits: ["update:modelValue"],
|
|
107
|
+
setup(__props, { emit: __emit }) {
|
|
108
|
+
const props = __props;
|
|
109
|
+
const emit = __emit;
|
|
110
|
+
const { rootClass } = useTabs(props, useId(), (value) => {
|
|
111
|
+
emit("update:modelValue", value);
|
|
112
|
+
});
|
|
113
|
+
const n1 = t0$3();
|
|
114
|
+
renderEffect(() => setClass(n1, unref(rootClass)));
|
|
115
|
+
setInsertionState(n1, null, 0);
|
|
116
|
+
createSlot("default", null, null, 1);
|
|
117
|
+
return n1;
|
|
118
|
+
}
|
|
119
|
+
}), [["__scopeId", "data-v-f9df84ad"]]);
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/components/tabs/tabs-list.vue?vue&type=script&setup=true&vapor=true&lang.ts
|
|
122
|
+
var t0$2 = template("<div data-v-f020ecc8 role=tablist>", 1);
|
|
123
|
+
delegateEvents("keydown");
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/components/tabs/tabs-list.vue
|
|
126
|
+
var tabs_list_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineVaporComponent({
|
|
127
|
+
name: "RpTabsList",
|
|
128
|
+
__name: "tabs-list",
|
|
129
|
+
setup(__props) {
|
|
130
|
+
const { listRef, rootClass, onKeydown } = useTabsList();
|
|
131
|
+
const _setTemplateRef = createTemplateRefSetter();
|
|
132
|
+
const n1 = t0$2();
|
|
133
|
+
renderEffect(() => setClass(n1, unref(rootClass)));
|
|
134
|
+
setInsertionState(n1, null, 0);
|
|
135
|
+
createSlot("default", null, null, 1);
|
|
136
|
+
n1.$evtkeydown = createInvoker((e) => unref(onKeydown)(e));
|
|
137
|
+
_setTemplateRef(n1, listRef, null, "listRef");
|
|
138
|
+
return n1;
|
|
139
|
+
}
|
|
140
|
+
}), [["__scopeId", "data-v-f020ecc8"]]);
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/components/tabs/tabs-trigger.vue?vue&type=script&setup=true&vapor=true&lang.ts
|
|
143
|
+
var t0$1 = template("<button data-v-7fa65d85 type=button role=tab>", 1);
|
|
144
|
+
delegateEvents("click");
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/components/tabs/tabs-trigger.vue
|
|
147
|
+
var tabs_trigger_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineVaporComponent({
|
|
148
|
+
name: "RpTabsTrigger",
|
|
149
|
+
__name: "tabs-trigger",
|
|
150
|
+
props: {
|
|
151
|
+
value: {},
|
|
152
|
+
disabled: {
|
|
153
|
+
type: Boolean,
|
|
154
|
+
default: false
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
setup(__props) {
|
|
158
|
+
const { tabs, isActive, rootClass, select } = useTabsTrigger(__props);
|
|
159
|
+
const n1 = t0$1();
|
|
160
|
+
renderEffect(() => {
|
|
161
|
+
const _value = __props.value;
|
|
162
|
+
const _isActive = unref(isActive);
|
|
163
|
+
setProp(n1, "id", unref(tabs).getTriggerId(_value));
|
|
164
|
+
setClass(n1, unref(rootClass));
|
|
165
|
+
setProp(n1, "disabled", __props.disabled || void 0);
|
|
166
|
+
setAttr(n1, "aria-selected", _isActive);
|
|
167
|
+
setAttr(n1, "aria-controls", unref(tabs).getPanelId(_value));
|
|
168
|
+
setProp(n1, "tabindex", _isActive ? 0 : -1);
|
|
169
|
+
setAttr(n1, "data-value", _value);
|
|
170
|
+
setAttr(n1, "data-state", _isActive ? "active" : "inactive");
|
|
171
|
+
setAttr(n1, "data-disabled", __props.disabled || void 0);
|
|
172
|
+
});
|
|
173
|
+
setInsertionState(n1, null, 0);
|
|
174
|
+
createSlot("default", null, null, 1);
|
|
175
|
+
n1.$evtclick = createInvoker((e) => unref(select)(e));
|
|
176
|
+
return n1;
|
|
177
|
+
}
|
|
178
|
+
}), [["__scopeId", "data-v-7fa65d85"]]);
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region src/components/tabs/tab-panel.vue?vue&type=script&setup=true&vapor=true&lang.ts
|
|
181
|
+
var t0 = template("<div data-v-6205e839 class=rp-tab-panel role=tabpanel tabindex=0>", 1);
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region src/components/tabs/tab-panel.vue
|
|
184
|
+
var tab_panel_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineVaporComponent({
|
|
185
|
+
name: "RpTabPanel",
|
|
186
|
+
__name: "tab-panel",
|
|
187
|
+
props: { value: {} },
|
|
188
|
+
setup(__props) {
|
|
189
|
+
const { tabs, isActive } = useTabPanel(__props);
|
|
190
|
+
return createIf(() => unref(isActive), () => {
|
|
191
|
+
const n3 = t0();
|
|
192
|
+
renderEffect(() => {
|
|
193
|
+
setProp(n3, "id", unref(tabs).getPanelId(__props.value));
|
|
194
|
+
setAttr(n3, "aria-labelledby", unref(tabs).getTriggerId(__props.value));
|
|
195
|
+
});
|
|
196
|
+
setInsertionState(n3, null, 0);
|
|
197
|
+
createSlot("default", null, null, 1);
|
|
198
|
+
return n3;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}), [["__scopeId", "data-v-6205e839"]]);
|
|
202
|
+
//#endregion
|
|
203
|
+
export { tabs_default as i, tabs_trigger_default as n, tabs_list_default as r, tab_panel_default as t };
|
|
204
|
+
|
|
205
|
+
//# sourceMappingURL=tabs.js.map
|
package/dist/tabs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tabs.js","names":[],"sources":["../src/components/tabs/types.ts","../src/components/tabs/useTabs.ts","../src/components/tabs/tabs.vue","../src/components/tabs/tabs.vue","../src/components/tabs/tabs-list.vue","../src/components/tabs/tabs-list.vue","../src/components/tabs/tabs-trigger.vue","../src/components/tabs/tabs-trigger.vue","../src/components/tabs/tab-panel.vue","../src/components/tabs/tab-panel.vue"],"sourcesContent":["import type { InjectionKey } from 'vue';\n\nexport interface TabsProps {\n modelValue: string;\n}\n\nexport interface TabPanelProps {\n value: string;\n}\n\nexport interface TabsTriggerProps {\n value: string;\n disabled?: boolean;\n}\n\nexport interface TabsContext {\n activeTab: string;\n select: (value: string) => void;\n getTriggerId: (value: string) => string;\n getPanelId: (value: string) => string;\n}\n\nexport const tabsKey = Symbol('tabs') as InjectionKey<TabsContext>;\n","import { computed, provide, ref } from 'vue';\nimport { useRequiredInject } from '@/composables/useRequiredInject';\nimport { bem } from '@/utils/bem';\nimport { tabsKey } from './types';\nimport type { TabPanelProps, TabsContext, TabsProps, TabsTriggerProps } from './types';\n\nfunction safeTabId(value: string) {\n return value.replace(/[^a-zA-Z0-9_-]/g, '-');\n}\n\nexport function useTabs(\n props: Readonly<TabsProps>,\n tabsId: string,\n emitUpdate: (value: string) => void,\n) {\n function select(value: string) {\n emitUpdate(value);\n }\n\n function getTriggerId(value: string) {\n return `${tabsId}-trigger-${safeTabId(value)}`;\n }\n\n function getPanelId(value: string) {\n return `${tabsId}-panel-${safeTabId(value)}`;\n }\n\n const rootClass = computed(() =>\n bem('rp-tabs'),\n );\n\n provide<TabsContext>(tabsKey, {\n get activeTab() { return props.modelValue; },\n select,\n getTriggerId,\n getPanelId,\n });\n\n return { rootClass };\n}\n\nfunction getEnabledTabs(list: HTMLElement | null) {\n if (!list) return [];\n return Array.from(list.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]'))\n .filter((tab) => !tab.disabled && tab.getAttribute('aria-disabled') !== 'true');\n}\n\nexport function useTabsList() {\n const tabs = useRequiredInject(tabsKey, 'RpTabsList');\n const listRef = ref<HTMLElement | null>(null);\n\n const rootClass = computed(() => bem('rp-tabs__list'));\n\n function focusTab(index: number) {\n const items = getEnabledTabs(listRef.value);\n if (items.length === 0) return;\n\n const next = (index + items.length) % items.length;\n const item = items[next]!;\n item.focus();\n\n const value = item.dataset.value;\n if (value) tabs.select(value);\n }\n\n function onKeydown(e: KeyboardEvent) {\n const keys = ['ArrowRight', 'ArrowDown', 'ArrowLeft', 'ArrowUp', 'Home', 'End'];\n if (!keys.includes(e.key)) return;\n\n const items = getEnabledTabs(listRef.value);\n if (items.length === 0) return;\n\n e.preventDefault();\n const current = items.indexOf(document.activeElement as HTMLButtonElement);\n\n if (e.key === 'Home') {\n focusTab(0);\n } else if (e.key === 'End') {\n focusTab(items.length - 1);\n } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n focusTab(current + 1);\n } else {\n focusTab(current - 1);\n }\n }\n\n return {\n listRef,\n rootClass,\n onKeydown,\n };\n}\n\nexport function useTabsTrigger(props: Readonly<TabsTriggerProps>) {\n const tabs = useRequiredInject(tabsKey, 'RpTabsTrigger');\n const isActive = computed(() => tabs.activeTab === props.value);\n\n const rootClass = computed(() =>\n bem('rp-tabs__trigger', {\n active: isActive.value,\n disabled: props.disabled,\n }),\n );\n\n function select() {\n if (!props.disabled) tabs.select(props.value);\n }\n\n return {\n tabs,\n isActive,\n rootClass,\n select,\n };\n}\n\nexport function useTabPanel(props: Readonly<TabPanelProps>) {\n const tabs = useRequiredInject(tabsKey, 'RpTabPanel');\n const isActive = computed(() => tabs.activeTab === props.value);\n\n return {\n tabs,\n isActive,\n };\n}\n","<template>\n <div :class=\"rootClass\">\n <slot />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useId } from 'vue';\nimport { useTabs } from './useTabs';\nimport type { TabsProps } from './types';\n\ndefineOptions({ name: 'RpTabs' });\n\nconst props = defineProps<TabsProps>();\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst tabsId = useId();\nconst { rootClass } = useTabs(props, tabsId, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./tabs.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div :class=\"rootClass\">\n <slot />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useId } from 'vue';\nimport { useTabs } from './useTabs';\nimport type { TabsProps } from './types';\n\ndefineOptions({ name: 'RpTabs' });\n\nconst props = defineProps<TabsProps>();\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst tabsId = useId();\nconst { rootClass } = useTabs(props, tabsId, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./tabs.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div :class=\"rootClass\" role=\"tablist\" ref=\"listRef\" @keydown=\"onKeydown\">\n <slot />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useTabsList } from './useTabs';\n\ndefineOptions({ name: 'RpTabsList' });\n\nconst { listRef, rootClass, onKeydown } = useTabsList();\nvoid listRef;\n</script>\n\n<style src=\"./tabs-list.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div :class=\"rootClass\" role=\"tablist\" ref=\"listRef\" @keydown=\"onKeydown\">\n <slot />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useTabsList } from './useTabs';\n\ndefineOptions({ name: 'RpTabsList' });\n\nconst { listRef, rootClass, onKeydown } = useTabsList();\nvoid listRef;\n</script>\n\n<style src=\"./tabs-list.scss\" lang=\"scss\" scoped></style>\n","<template>\n <button\n :id=\"tabs.getTriggerId(value)\"\n type=\"button\"\n role=\"tab\"\n :class=\"rootClass\"\n :disabled=\"disabled || undefined\"\n :aria-selected=\"isActive\"\n :aria-controls=\"tabs.getPanelId(value)\"\n :tabindex=\"isActive ? 0 : -1\"\n :data-value=\"value\"\n :data-state=\"isActive ? 'active' : 'inactive'\"\n :data-disabled=\"disabled || undefined\"\n @click=\"select\"\n >\n <slot />\n </button>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useTabsTrigger } from './useTabs';\nimport type { TabsTriggerProps } from './types';\n\ndefineOptions({ name: 'RpTabsTrigger' });\n\nconst props = withDefaults(defineProps<TabsTriggerProps>(), {\n disabled: false,\n});\n\nconst { tabs, isActive, rootClass, select } = useTabsTrigger(props);\n</script>\n\n<style src=\"./tabs-trigger.scss\" lang=\"scss\" scoped></style>\n","<template>\n <button\n :id=\"tabs.getTriggerId(value)\"\n type=\"button\"\n role=\"tab\"\n :class=\"rootClass\"\n :disabled=\"disabled || undefined\"\n :aria-selected=\"isActive\"\n :aria-controls=\"tabs.getPanelId(value)\"\n :tabindex=\"isActive ? 0 : -1\"\n :data-value=\"value\"\n :data-state=\"isActive ? 'active' : 'inactive'\"\n :data-disabled=\"disabled || undefined\"\n @click=\"select\"\n >\n <slot />\n </button>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useTabsTrigger } from './useTabs';\nimport type { TabsTriggerProps } from './types';\n\ndefineOptions({ name: 'RpTabsTrigger' });\n\nconst props = withDefaults(defineProps<TabsTriggerProps>(), {\n disabled: false,\n});\n\nconst { tabs, isActive, rootClass, select } = useTabsTrigger(props);\n</script>\n\n<style src=\"./tabs-trigger.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div\n v-if=\"isActive\"\n :id=\"tabs.getPanelId(value)\"\n class=\"rp-tab-panel\"\n role=\"tabpanel\"\n tabindex=\"0\"\n :aria-labelledby=\"tabs.getTriggerId(value)\"\n >\n <slot />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useTabPanel } from './useTabs';\nimport type { TabPanelProps } from './types';\n\ndefineOptions({ name: 'RpTabPanel' });\n\nconst props = defineProps<TabPanelProps>();\n\nconst { tabs, isActive } = useTabPanel(props);\n</script>\n\n<style src=\"./tab-panel.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div\n v-if=\"isActive\"\n :id=\"tabs.getPanelId(value)\"\n class=\"rp-tab-panel\"\n role=\"tabpanel\"\n tabindex=\"0\"\n :aria-labelledby=\"tabs.getTriggerId(value)\"\n >\n <slot />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useTabPanel } from './useTabs';\nimport type { TabPanelProps } from './types';\n\ndefineOptions({ name: 'RpTabPanel' });\n\nconst props = defineProps<TabPanelProps>();\n\nconst { tabs, isActive } = useTabPanel(props);\n</script>\n\n<style src=\"./tab-panel.scss\" lang=\"scss\" scoped></style>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
.rp-textarea[data-v-84020885] {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
font-family: var(--rp-font-family);
|
|
4
|
+
font-weight: var(--rp-font-weight-normal);
|
|
5
|
+
background-color: var(--rp-color-control-bg);
|
|
6
|
+
border: var(--rp-border-width-thin) solid var(--rp-color-control-border);
|
|
7
|
+
transition: border-color var(--rp-transition-fast), box-shadow var(--rp-transition-fast);
|
|
8
|
+
}
|
|
9
|
+
.rp-textarea[data-v-84020885]:hover:not(.rp-textarea--disabled) {
|
|
10
|
+
border-color: var(--rp-color-control-border-hover);
|
|
11
|
+
}
|
|
12
|
+
.rp-textarea[data-v-84020885]:focus-within:not(.rp-textarea--disabled) {
|
|
13
|
+
border-color: var(--rp-color-control-border-focus);
|
|
14
|
+
box-shadow: 0 0 0 var(--rp-border-width-medium) var(--rp-color-focus-ring);
|
|
15
|
+
}
|
|
16
|
+
.rp-textarea[data-v-84020885] {
|
|
17
|
+
padding: var(--rp-spacing-3) var(--rp-spacing-4);
|
|
18
|
+
font-size: var(--rp-font-size-base);
|
|
19
|
+
border-radius: var(--rp-radius-lg);
|
|
20
|
+
}
|
|
21
|
+
.rp-textarea--disabled[data-v-84020885] {
|
|
22
|
+
opacity: var(--rp-opacity-disabled);
|
|
23
|
+
cursor: not-allowed;
|
|
24
|
+
}
|
|
25
|
+
.rp-textarea--invalid[data-v-84020885] {
|
|
26
|
+
border-color: var(--rp-color-danger-fg);
|
|
27
|
+
}
|
|
28
|
+
.rp-textarea--readonly[data-v-84020885] {
|
|
29
|
+
background-color: var(--rp-color-control-readonly-bg);
|
|
30
|
+
}
|
|
31
|
+
.rp-textarea__native[data-v-84020885] {
|
|
32
|
+
flex: 1;
|
|
33
|
+
min-width: 0;
|
|
34
|
+
border: none;
|
|
35
|
+
outline: none;
|
|
36
|
+
background: transparent;
|
|
37
|
+
font: inherit;
|
|
38
|
+
color: var(--rp-color-control-fg);
|
|
39
|
+
line-height: var(--rp-line-height-relaxed);
|
|
40
|
+
}
|
|
41
|
+
.rp-textarea__native[data-v-84020885]::placeholder {
|
|
42
|
+
color: var(--rp-color-control-placeholder);
|
|
43
|
+
}
|
|
44
|
+
.rp-textarea__native[data-v-84020885]:disabled {
|
|
45
|
+
cursor: not-allowed;
|
|
46
|
+
}
|
package/dist/textarea.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import './textarea.css';
|
|
2
|
+
import { n as bem, t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper.js";
|
|
3
|
+
import { t as useControlState } from "./useControlState.js";
|
|
4
|
+
import { child, computed, createInvoker, defineVaporComponent, delegateEvents, renderEffect, setAttr, setClass, setProp, setValue, template, unref } from "vue";
|
|
5
|
+
//#region src/components/textarea/useTextarea.ts
|
|
6
|
+
function useTextarea(props, emitUpdate) {
|
|
7
|
+
const control = useControlState(props);
|
|
8
|
+
const rootClass = computed(() => bem("rp-textarea", {
|
|
9
|
+
disabled: control.disabled,
|
|
10
|
+
invalid: control.invalid,
|
|
11
|
+
readonly: props.readonly
|
|
12
|
+
}));
|
|
13
|
+
function onInput(e) {
|
|
14
|
+
emitUpdate(e.target.value);
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
control,
|
|
18
|
+
rootClass,
|
|
19
|
+
onInput
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/components/textarea/textarea.vue?vue&type=script&setup=true&vapor=true&lang.ts
|
|
24
|
+
var t0 = template("<div data-v-84020885><textarea data-v-84020885 class=rp-textarea__native>", 1);
|
|
25
|
+
delegateEvents("input");
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/components/textarea/textarea.vue
|
|
28
|
+
var textarea_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineVaporComponent({
|
|
29
|
+
name: "RpTextarea",
|
|
30
|
+
__name: "textarea",
|
|
31
|
+
props: {
|
|
32
|
+
id: {},
|
|
33
|
+
name: {},
|
|
34
|
+
modelValue: {},
|
|
35
|
+
placeholder: { default: "" },
|
|
36
|
+
rows: { default: 3 },
|
|
37
|
+
disabled: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: void 0
|
|
40
|
+
},
|
|
41
|
+
readonly: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
default: false
|
|
44
|
+
},
|
|
45
|
+
required: {
|
|
46
|
+
type: Boolean,
|
|
47
|
+
default: void 0
|
|
48
|
+
},
|
|
49
|
+
invalid: {
|
|
50
|
+
type: Boolean,
|
|
51
|
+
default: void 0
|
|
52
|
+
},
|
|
53
|
+
ariaLabel: {},
|
|
54
|
+
describedby: {},
|
|
55
|
+
labelledby: {}
|
|
56
|
+
},
|
|
57
|
+
emits: ["update:modelValue"],
|
|
58
|
+
setup(__props, { emit: __emit }) {
|
|
59
|
+
const props = __props;
|
|
60
|
+
const emit = __emit;
|
|
61
|
+
const { control, rootClass, onInput } = useTextarea(props, (value) => {
|
|
62
|
+
emit("update:modelValue", value);
|
|
63
|
+
});
|
|
64
|
+
const n1 = t0();
|
|
65
|
+
const n0 = child(n1);
|
|
66
|
+
n0.$evtinput = createInvoker((e) => unref(onInput)(e));
|
|
67
|
+
renderEffect(() => {
|
|
68
|
+
const _control = unref(control);
|
|
69
|
+
const _control_required = _control.required;
|
|
70
|
+
setClass(n1, unref(rootClass));
|
|
71
|
+
setProp(n0, "id", _control.id);
|
|
72
|
+
setProp(n0, "name", __props.name);
|
|
73
|
+
setValue(n0, __props.modelValue);
|
|
74
|
+
setProp(n0, "placeholder", __props.placeholder);
|
|
75
|
+
setProp(n0, "rows", __props.rows);
|
|
76
|
+
setProp(n0, "disabled", _control.disabled || void 0);
|
|
77
|
+
setProp(n0, "readonly", __props.readonly || void 0);
|
|
78
|
+
setProp(n0, "required", _control_required || void 0);
|
|
79
|
+
setAttr(n0, "aria-label", __props.ariaLabel || void 0);
|
|
80
|
+
setAttr(n0, "aria-labelledby", _control.ariaLabelledby);
|
|
81
|
+
setAttr(n0, "aria-describedby", _control.ariaDescribedby);
|
|
82
|
+
setAttr(n0, "aria-invalid", _control.invalid || void 0);
|
|
83
|
+
setAttr(n0, "aria-required", _control_required || void 0);
|
|
84
|
+
});
|
|
85
|
+
return n1;
|
|
86
|
+
}
|
|
87
|
+
}), [["__scopeId", "data-v-84020885"]]);
|
|
88
|
+
//#endregion
|
|
89
|
+
export { textarea_default as t };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=textarea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textarea.js","names":[],"sources":["../src/components/textarea/useTextarea.ts","../src/components/textarea/textarea.vue","../src/components/textarea/textarea.vue"],"sourcesContent":["import { computed } from 'vue';\nimport { useControlState } from '@/composables/useControlState';\nimport { bem } from '@/utils/bem';\nimport type { TextareaProps } from './types';\n\nexport function useTextarea(\n props: Readonly<TextareaProps>,\n emitUpdate: (value: string) => void,\n) {\n const control = useControlState(props);\n\n const rootClass = computed(() =>\n bem('rp-textarea', {\n disabled: control.disabled,\n invalid: control.invalid,\n readonly: props.readonly,\n }),\n );\n\n function onInput(e: Event) {\n emitUpdate((e.target as HTMLTextAreaElement).value);\n }\n\n return {\n control,\n rootClass,\n onInput,\n };\n}\n","<template>\n <div :class=\"rootClass\">\n <textarea\n :id=\"control.id\"\n :name=\"name\"\n class=\"rp-textarea__native\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :rows=\"rows\"\n :disabled=\"control.disabled || undefined\"\n :readonly=\"readonly || undefined\"\n :required=\"control.required || 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 @input=\"onInput\"\n />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useTextarea } from './useTextarea';\nimport type { TextareaProps } from './types';\n\ndefineOptions({ name: 'RpTextarea' });\n\nconst props = withDefaults(defineProps<TextareaProps>(), {\n placeholder: '',\n rows: 3,\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n readonly: false,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst { control, rootClass, onInput } = useTextarea(props, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./textarea.scss\" lang=\"scss\" scoped></style>\n","<template>\n <div :class=\"rootClass\">\n <textarea\n :id=\"control.id\"\n :name=\"name\"\n class=\"rp-textarea__native\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :rows=\"rows\"\n :disabled=\"control.disabled || undefined\"\n :readonly=\"readonly || undefined\"\n :required=\"control.required || 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 @input=\"onInput\"\n />\n </div>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useTextarea } from './useTextarea';\nimport type { TextareaProps } from './types';\n\ndefineOptions({ name: 'RpTextarea' });\n\nconst props = withDefaults(defineProps<TextareaProps>(), {\n placeholder: '',\n rows: 3,\n disabled: undefined,\n required: undefined,\n invalid: undefined,\n readonly: false,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst { control, rootClass, onInput } = useTextarea(props, (value) => {\n emit('update:modelValue', value);\n});\n</script>\n\n<style src=\"./textarea.scss\" lang=\"scss\" scoped></style>\n"],"mappings":";;;;AAKA,SAAgB,YACZ,OACA,YACF;CACE,MAAM,UAAU,gBAAgB,KAAK;CAErC,MAAM,YAAY,eACd,IAAI,eAAe;EACf,UAAU,QAAQ;EAClB,SAAS,QAAQ;EACjB,UAAU,MAAM;CACpB,CAAC,CACL;CAEA,SAAS,QAAQ,GAAU;EACvB,WAAY,EAAE,OAA+B,KAAK;CACtD;CAEA,OAAO;EACH;EACA;EACA;CACJ;AACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA,MAAM,QAAQ;EASd,MAAM,OAAO;EAIb,MAAM,EAAE,SAAS,WAAW,YAAY,YAAY,QAAQ,UAAU;GAClE,KAAK,qBAAqB,KAAK;EACnC,CAAC;;;sCA1BmB,MAAA,OAAA,CAAO,CAAA,CAAA,CAAA;;;;gBAhBV,MAAA,SAAA,CAAS;eAEb,MAAI,SAAO,EAAA;eACX,QAAM,QAAA,IAAI;gBAEH,QAAA,UAAU;eACjB,eAAa,QAAA,WAAW;eACxB,QAAM,QAAA,IAAI;eACV,YAAU,SAAO,YAAa,KAAA,CAAS;eACvC,YAAU,QAAA,YAAY,KAAA,CAAS;eAC/B,YAAU,qBAAoB,KAAA,CAAS;eACvC,cAAY,QAAA,aAAa,KAAA,CAAS;eAClC,mBAAiB,SAAO,cAAA;eACxB,oBAAkB,SAAO,eAAA;eACzB,gBAAc,SAAO,WAAY,KAAA,CAAS;eAC1C,iBAAe,qBAAoB,KAAA,CAAS"}
|
package/dist/tooltip.css
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
.rp-tooltip[data-v-87be39f8] {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: inline-flex;
|
|
4
|
+
}
|
|
5
|
+
.rp-tooltip__tip[data-v-87be39f8] {
|
|
6
|
+
--_arrow: 5px;
|
|
7
|
+
--_gap: var(--rp-border-width-medium);
|
|
8
|
+
position: absolute;
|
|
9
|
+
z-index: var(--rp-z-index-tooltip);
|
|
10
|
+
padding: var(--rp-spacing-1) var(--rp-spacing-2);
|
|
11
|
+
font-family: var(--rp-font-family);
|
|
12
|
+
font-size: var(--rp-font-size-xs);
|
|
13
|
+
font-weight: var(--rp-font-weight-medium);
|
|
14
|
+
line-height: var(--rp-line-height-normal);
|
|
15
|
+
color: var(--rp-color-text-inverted);
|
|
16
|
+
background-color: var(--rp-color-surface-inverted);
|
|
17
|
+
border-radius: var(--rp-radius-md);
|
|
18
|
+
white-space: nowrap;
|
|
19
|
+
pointer-events: none;
|
|
20
|
+
animation: rp-tooltip-fade-87be39f8 var(--rp-transition-fast);
|
|
21
|
+
}
|
|
22
|
+
.rp-tooltip__tip[data-v-87be39f8]::after {
|
|
23
|
+
content: "";
|
|
24
|
+
position: absolute;
|
|
25
|
+
border: var(--_arrow) solid transparent;
|
|
26
|
+
}
|
|
27
|
+
.rp-tooltip__tip--top[data-v-87be39f8] {
|
|
28
|
+
bottom: calc(100% + var(--_arrow) + var(--_gap));
|
|
29
|
+
left: 50%;
|
|
30
|
+
transform: translateX(-50%);
|
|
31
|
+
}
|
|
32
|
+
.rp-tooltip__tip--top[data-v-87be39f8]::after {
|
|
33
|
+
top: 100%;
|
|
34
|
+
left: 50%;
|
|
35
|
+
transform: translateX(-50%);
|
|
36
|
+
border-top-color: var(--rp-color-surface-inverted);
|
|
37
|
+
}
|
|
38
|
+
.rp-tooltip__tip--bottom[data-v-87be39f8] {
|
|
39
|
+
top: calc(100% + var(--_arrow) + var(--_gap));
|
|
40
|
+
left: 50%;
|
|
41
|
+
transform: translateX(-50%);
|
|
42
|
+
}
|
|
43
|
+
.rp-tooltip__tip--bottom[data-v-87be39f8]::after {
|
|
44
|
+
bottom: 100%;
|
|
45
|
+
left: 50%;
|
|
46
|
+
transform: translateX(-50%);
|
|
47
|
+
border-bottom-color: var(--rp-color-surface-inverted);
|
|
48
|
+
}
|
|
49
|
+
.rp-tooltip__tip--left[data-v-87be39f8] {
|
|
50
|
+
right: calc(100% + var(--_arrow) + var(--_gap));
|
|
51
|
+
top: 50%;
|
|
52
|
+
transform: translateY(-50%);
|
|
53
|
+
}
|
|
54
|
+
.rp-tooltip__tip--left[data-v-87be39f8]::after {
|
|
55
|
+
left: 100%;
|
|
56
|
+
top: 50%;
|
|
57
|
+
transform: translateY(-50%);
|
|
58
|
+
border-left-color: var(--rp-color-surface-inverted);
|
|
59
|
+
}
|
|
60
|
+
.rp-tooltip__tip--right[data-v-87be39f8] {
|
|
61
|
+
left: calc(100% + var(--_arrow) + var(--_gap));
|
|
62
|
+
top: 50%;
|
|
63
|
+
transform: translateY(-50%);
|
|
64
|
+
}
|
|
65
|
+
.rp-tooltip__tip--right[data-v-87be39f8]::after {
|
|
66
|
+
right: 100%;
|
|
67
|
+
top: 50%;
|
|
68
|
+
transform: translateY(-50%);
|
|
69
|
+
border-right-color: var(--rp-color-surface-inverted);
|
|
70
|
+
}
|
|
71
|
+
@keyframes rp-tooltip-fade-87be39f8 {
|
|
72
|
+
from {
|
|
73
|
+
opacity: 0;
|
|
74
|
+
}
|
|
75
|
+
to {
|
|
76
|
+
opacity: 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
package/dist/tooltip.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import './tooltip.css';
|
|
2
|
+
import { n as bem, t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper.js";
|
|
3
|
+
import { computed, createIf, createInvoker, createSlot, defineVaporComponent, delegateEvents, on, onBeforeUnmount, ref, renderEffect, setAttr, setClass, setInsertionState, setProp, template, unref, useId } from "vue";
|
|
4
|
+
//#region src/composables/useDelayedOpen.ts
|
|
5
|
+
function readOption(value, fallback) {
|
|
6
|
+
return typeof value === "function" ? value() ?? fallback : value ?? fallback;
|
|
7
|
+
}
|
|
8
|
+
function useDelayedOpen(options = {}) {
|
|
9
|
+
const isOpen = ref(false);
|
|
10
|
+
let openTimer = null;
|
|
11
|
+
function clearTimers() {
|
|
12
|
+
if (openTimer) {
|
|
13
|
+
clearTimeout(openTimer);
|
|
14
|
+
openTimer = null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function isDisabled() {
|
|
18
|
+
return readOption(options.disabled, false);
|
|
19
|
+
}
|
|
20
|
+
function open() {
|
|
21
|
+
if (isDisabled()) return;
|
|
22
|
+
const delay = readOption(options.openDelay, 0);
|
|
23
|
+
if (delay <= 0) {
|
|
24
|
+
isOpen.value = true;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (openTimer) clearTimeout(openTimer);
|
|
28
|
+
openTimer = setTimeout(() => {
|
|
29
|
+
isOpen.value = true;
|
|
30
|
+
openTimer = null;
|
|
31
|
+
}, delay);
|
|
32
|
+
}
|
|
33
|
+
function closeImmediate() {
|
|
34
|
+
clearTimers();
|
|
35
|
+
isOpen.value = false;
|
|
36
|
+
}
|
|
37
|
+
onBeforeUnmount(clearTimers);
|
|
38
|
+
return {
|
|
39
|
+
isOpen,
|
|
40
|
+
open,
|
|
41
|
+
closeImmediate
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/components/tooltip/useTooltip.ts
|
|
46
|
+
function useTooltip(props) {
|
|
47
|
+
const tooltipId = useId();
|
|
48
|
+
const visibility = useDelayedOpen({
|
|
49
|
+
openDelay: () => props.delay,
|
|
50
|
+
disabled: () => props.disabled
|
|
51
|
+
});
|
|
52
|
+
function onShow() {
|
|
53
|
+
visibility.open();
|
|
54
|
+
}
|
|
55
|
+
function onHide() {
|
|
56
|
+
visibility.closeImmediate();
|
|
57
|
+
}
|
|
58
|
+
const tipClass = computed(() => bem("rp-tooltip__tip", props.placement ?? "top"));
|
|
59
|
+
return {
|
|
60
|
+
tooltipId,
|
|
61
|
+
isVisible: visibility.isOpen,
|
|
62
|
+
tipClass,
|
|
63
|
+
onShow,
|
|
64
|
+
onHide
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/components/tooltip/tooltip.vue?vue&type=script&setup=true&vapor=true&lang.ts
|
|
69
|
+
var t0 = template("<span data-v-87be39f8 role=tooltip>");
|
|
70
|
+
var t1 = template("<span data-v-87be39f8 class=rp-tooltip>", 1);
|
|
71
|
+
delegateEvents("focusin", "focusout");
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/components/tooltip/tooltip.vue
|
|
74
|
+
var tooltip_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineVaporComponent({
|
|
75
|
+
name: "RpTooltip",
|
|
76
|
+
__name: "tooltip",
|
|
77
|
+
props: {
|
|
78
|
+
placement: { default: "top" },
|
|
79
|
+
delay: { default: 200 },
|
|
80
|
+
disabled: {
|
|
81
|
+
type: Boolean,
|
|
82
|
+
default: false
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
setup(__props, { slots: $slots }) {
|
|
86
|
+
const { tooltipId, isVisible, tipClass, onShow, onHide } = useTooltip(__props);
|
|
87
|
+
const n5 = t1();
|
|
88
|
+
renderEffect(() => setAttr(n5, "aria-describedby", unref(isVisible) && !__props.disabled && $slots.content ? unref(tooltipId) : void 0));
|
|
89
|
+
setInsertionState(n5, null, 0);
|
|
90
|
+
createSlot("default", null, null, 1);
|
|
91
|
+
setInsertionState(n5, null, 1);
|
|
92
|
+
createIf(() => unref(isVisible) && !__props.disabled && $slots.content, () => {
|
|
93
|
+
const n4 = t0();
|
|
94
|
+
renderEffect(() => {
|
|
95
|
+
setProp(n4, "id", unref(tooltipId));
|
|
96
|
+
setClass(n4, unref(tipClass));
|
|
97
|
+
});
|
|
98
|
+
setInsertionState(n4, null, 0);
|
|
99
|
+
createSlot("content", null, null, 1);
|
|
100
|
+
return n4;
|
|
101
|
+
});
|
|
102
|
+
on(n5, "mouseenter", (e) => unref(onShow)(e));
|
|
103
|
+
on(n5, "mouseleave", (e) => unref(onHide)(e));
|
|
104
|
+
n5.$evtfocusin = createInvoker((e) => unref(onShow)(e));
|
|
105
|
+
n5.$evtfocusout = createInvoker((e) => unref(onHide)(e));
|
|
106
|
+
return n5;
|
|
107
|
+
}
|
|
108
|
+
}), [["__scopeId", "data-v-87be39f8"]]);
|
|
109
|
+
//#endregion
|
|
110
|
+
export { tooltip_default as t };
|
|
111
|
+
|
|
112
|
+
//# sourceMappingURL=tooltip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip.js","names":[],"sources":["../src/composables/useDelayedOpen.ts","../src/components/tooltip/useTooltip.ts","../src/components/tooltip/tooltip.vue","../src/components/tooltip/tooltip.vue"],"sourcesContent":["import { onBeforeUnmount, ref } from 'vue';\n\nexport interface UseDelayedOpenOptions {\n openDelay?: number | (() => number | undefined);\n disabled?: boolean | (() => boolean | undefined);\n}\n\nfunction readOption<T>(value: T | (() => T | undefined) | undefined, fallback: T): T {\n return typeof value === 'function'\n ? (value as () => T | undefined)() ?? fallback\n : value ?? fallback;\n}\n\nexport function useDelayedOpen(options: UseDelayedOpenOptions = {}) {\n const isOpen = ref(false);\n let openTimer: ReturnType<typeof setTimeout> | null = null;\n\n function clearTimers() {\n if (openTimer) { clearTimeout(openTimer); openTimer = null; }\n }\n\n function isDisabled() {\n return readOption(options.disabled, false);\n }\n\n function open() {\n if (isDisabled()) return;\n const delay = readOption(options.openDelay, 0);\n if (delay <= 0) {\n isOpen.value = true;\n return;\n }\n if (openTimer) clearTimeout(openTimer);\n openTimer = setTimeout(() => { isOpen.value = true; openTimer = null; }, delay);\n }\n\n function closeImmediate() {\n clearTimers();\n isOpen.value = false;\n }\n\n onBeforeUnmount(clearTimers);\n\n return {\n isOpen,\n open,\n closeImmediate,\n };\n}\n","import { computed, useId } from 'vue';\nimport { useDelayedOpen } from '@/composables/useDelayedOpen';\nimport { bem } from '@/utils/bem';\nimport type { TooltipProps } from './types';\n\nexport function useTooltip(props: Readonly<TooltipProps>) {\n const tooltipId = useId();\n const visibility = useDelayedOpen({\n openDelay: () => props.delay,\n disabled: () => props.disabled,\n });\n\n function onShow() {\n visibility.open();\n }\n\n function onHide() {\n visibility.closeImmediate();\n }\n\n const tipClass = computed(() =>\n bem('rp-tooltip__tip', props.placement ?? 'top'),\n );\n\n return {\n tooltipId,\n isVisible: visibility.isOpen,\n tipClass,\n onShow,\n onHide,\n };\n}\n","<template>\n <span\n class=\"rp-tooltip\"\n :aria-describedby=\"isVisible && !disabled && $slots.content ? tooltipId : undefined\"\n @mouseenter=\"onShow\"\n @mouseleave=\"onHide\"\n @focusin=\"onShow\"\n @focusout=\"onHide\"\n >\n <slot />\n <span v-if=\"isVisible && !disabled && $slots.content\" :id=\"tooltipId\" :class=\"tipClass\" role=\"tooltip\">\n <slot name=\"content\" />\n </span>\n </span>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useTooltip } from './useTooltip';\nimport type { TooltipProps } from './types';\n\ndefineOptions({ name: 'RpTooltip' });\n\nconst props = withDefaults(defineProps<TooltipProps>(), {\n placement: 'top',\n delay: 200,\n disabled: false,\n});\n\nconst { tooltipId, isVisible, tipClass, onShow, onHide } = useTooltip(props);\n</script>\n\n<style src=\"./tooltip.scss\" lang=\"scss\" scoped></style>\n","<template>\n <span\n class=\"rp-tooltip\"\n :aria-describedby=\"isVisible && !disabled && $slots.content ? tooltipId : undefined\"\n @mouseenter=\"onShow\"\n @mouseleave=\"onHide\"\n @focusin=\"onShow\"\n @focusout=\"onHide\"\n >\n <slot />\n <span v-if=\"isVisible && !disabled && $slots.content\" :id=\"tooltipId\" :class=\"tipClass\" role=\"tooltip\">\n <slot name=\"content\" />\n </span>\n </span>\n</template>\n\n<script lang=\"ts\" setup vapor>\nimport { useTooltip } from './useTooltip';\nimport type { TooltipProps } from './types';\n\ndefineOptions({ name: 'RpTooltip' });\n\nconst props = withDefaults(defineProps<TooltipProps>(), {\n placement: 'top',\n delay: 200,\n disabled: false,\n});\n\nconst { tooltipId, isVisible, tipClass, onShow, onHide } = useTooltip(props);\n</script>\n\n<style src=\"./tooltip.scss\" lang=\"scss\" scoped></style>\n"],"mappings":";;;AAOA,SAAS,WAAc,OAA8C,UAAgB;CACjF,OAAO,OAAO,UAAU,aACjB,MAA8B,KAAK,WACpC,SAAS;AACnB;AAEA,SAAgB,eAAe,UAAiC,CAAC,GAAG;CAChE,MAAM,SAAS,IAAI,KAAK;CACxB,IAAI,YAAkD;CAEtD,SAAS,cAAc;EACnB,IAAI,WAAW;GAAE,aAAa,SAAS;GAAG,YAAY;EAAM;CAChE;CAEA,SAAS,aAAa;EAClB,OAAO,WAAW,QAAQ,UAAU,KAAK;CAC7C;CAEA,SAAS,OAAO;EACZ,IAAI,WAAW,GAAG;EAClB,MAAM,QAAQ,WAAW,QAAQ,WAAW,CAAC;EAC7C,IAAI,SAAS,GAAG;GACZ,OAAO,QAAQ;GACf;EACJ;EACA,IAAI,WAAW,aAAa,SAAS;EACrC,YAAY,iBAAiB;GAAE,OAAO,QAAQ;GAAM,YAAY;EAAM,GAAG,KAAK;CAClF;CAEA,SAAS,iBAAiB;EACtB,YAAY;EACZ,OAAO,QAAQ;CACnB;CAEA,gBAAgB,WAAW;CAE3B,OAAO;EACH;EACA;EACA;CACJ;AACJ;;;AC3CA,SAAgB,WAAW,OAA+B;CACtD,MAAM,YAAY,MAAM;CACxB,MAAM,aAAa,eAAe;EAC9B,iBAAiB,MAAM;EACvB,gBAAgB,MAAM;CAC1B,CAAC;CAED,SAAS,SAAS;EACd,WAAW,KAAK;CACpB;CAEA,SAAS,SAAS;EACd,WAAW,eAAe;CAC9B;CAEA,MAAM,WAAW,eACb,IAAI,mBAAmB,MAAM,aAAa,KAAK,CACnD;CAEA,OAAO;EACH;EACA,WAAW,WAAW;EACtB;EACA;EACA;CACJ;AACJ;;;;;;;;;;;;;;;;;;;;ECHA,MAAM,EAAE,WAAW,WAAW,UAAU,QAAQ,WAAW,WAAW,OAAK;;iCAzBlE,oBAAkB,MAAA,SAAA,KAAS,CAAK,QAAA,YAAY,OAAM,UAAW,MAAA,SAAA,IAAY,KAAA,CAAS,CAAA;;;;iBAOvE,MAAA,SAAA,KAAS,CAAK,QAAA,YAAY,OAAM,eAAA;;;gBAAW,MAAI,MAAA,SAAA,CAAS;iBAAU,MAAA,QAAA,CAAQ;;;cAC5E,WAAc,MAAA,MAAA,CAAA;;;SAPvB,eAAU,MAAE,MAAA,MAAA,CAAM,CAAA,CAAA,CAAA;SAClB,eAAU,MAAE,MAAA,MAAA,CAAM,CAAA,CAAA,CAAA;wCACT,MAAA,MAAA,CAAM,CAAA,CAAA,CAAA;yCACL,MAAA,MAAA,CAAM,CAAA,CAAA,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { computed } from "vue";
|
|
2
|
+
//#region src/composables/useControlState.ts
|
|
3
|
+
function mergeIds(...values) {
|
|
4
|
+
const ids = values.flatMap((value) => value?.split(/\s+/) ?? []).filter(Boolean);
|
|
5
|
+
return ids.length > 0 ? Array.from(new Set(ids)).join(" ") : void 0;
|
|
6
|
+
}
|
|
7
|
+
function useControlState(options = {}) {
|
|
8
|
+
const id = computed(() => options.id);
|
|
9
|
+
const disabled = computed(() => options.disabled ?? false);
|
|
10
|
+
const required = computed(() => options.required ?? false);
|
|
11
|
+
const invalid = computed(() => options.invalid ?? false);
|
|
12
|
+
const ariaDescribedby = computed(() => mergeIds(options.describedby));
|
|
13
|
+
const ariaLabelledby = computed(() => mergeIds(options.labelledby));
|
|
14
|
+
return {
|
|
15
|
+
get id() {
|
|
16
|
+
return id.value;
|
|
17
|
+
},
|
|
18
|
+
get disabled() {
|
|
19
|
+
return disabled.value;
|
|
20
|
+
},
|
|
21
|
+
get required() {
|
|
22
|
+
return required.value;
|
|
23
|
+
},
|
|
24
|
+
get invalid() {
|
|
25
|
+
return invalid.value;
|
|
26
|
+
},
|
|
27
|
+
get ariaDescribedby() {
|
|
28
|
+
return ariaDescribedby.value;
|
|
29
|
+
},
|
|
30
|
+
get ariaLabelledby() {
|
|
31
|
+
return ariaLabelledby.value;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { useControlState as t };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=useControlState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useControlState.js","names":[],"sources":["../src/composables/useControlState.ts"],"sourcesContent":["import { computed } from 'vue';\n\nexport interface ControlStateOptions {\n id?: string;\n disabled?: boolean;\n required?: boolean;\n invalid?: boolean;\n describedby?: string;\n labelledby?: string;\n}\n\nexport interface ControlState {\n id: string | undefined;\n disabled: boolean;\n required: boolean;\n invalid: boolean;\n ariaDescribedby: string | undefined;\n ariaLabelledby: string | undefined;\n}\n\nfunction mergeIds(...values: Array<string | undefined>): string | undefined {\n const ids = values\n .flatMap((value) => value?.split(/\\s+/) ?? [])\n .filter(Boolean);\n return ids.length > 0 ? Array.from(new Set(ids)).join(' ') : undefined;\n}\n\nexport function useControlState(options: ControlStateOptions = {}): ControlState {\n const id = computed(() => options.id);\n const disabled = computed(() => options.disabled ?? false);\n const required = computed(() => options.required ?? false);\n const invalid = computed(() => options.invalid ?? false);\n\n const ariaDescribedby = computed(() => mergeIds(options.describedby));\n const ariaLabelledby = computed(() => mergeIds(options.labelledby));\n\n return {\n get id() { return id.value; },\n get disabled() { return disabled.value; },\n get required() { return required.value; },\n get invalid() { return invalid.value; },\n get ariaDescribedby() { return ariaDescribedby.value; },\n get ariaLabelledby() { return ariaLabelledby.value; },\n };\n}\n"],"mappings":";;AAoBA,SAAS,SAAS,GAAG,QAAuD;CACxE,MAAM,MAAM,OACP,SAAS,UAAU,OAAO,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,CAC7C,OAAO,OAAO;CACnB,OAAO,IAAI,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAA;AACjE;AAEA,SAAgB,gBAAgB,UAA+B,CAAC,GAAiB;CAC7E,MAAM,KAAK,eAAe,QAAQ,EAAE;CACpC,MAAM,WAAW,eAAe,QAAQ,YAAY,KAAK;CACzD,MAAM,WAAW,eAAe,QAAQ,YAAY,KAAK;CACzD,MAAM,UAAU,eAAe,QAAQ,WAAW,KAAK;CAEvD,MAAM,kBAAkB,eAAe,SAAS,QAAQ,WAAW,CAAC;CACpE,MAAM,iBAAiB,eAAe,SAAS,QAAQ,UAAU,CAAC;CAElE,OAAO;EACH,IAAI,KAAK;GAAE,OAAO,GAAG;EAAO;EAC5B,IAAI,WAAW;GAAE,OAAO,SAAS;EAAO;EACxC,IAAI,WAAW;GAAE,OAAO,SAAS;EAAO;EACxC,IAAI,UAAU;GAAE,OAAO,QAAQ;EAAO;EACtC,IAAI,kBAAkB;GAAE,OAAO,gBAAgB;EAAO;EACtD,IAAI,iBAAiB;GAAE,OAAO,eAAe;EAAO;CACxD;AACJ"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { inject } from "vue";
|
|
2
|
+
//#region src/composables/useRequiredInject.ts
|
|
3
|
+
function useRequiredInject(key, componentName) {
|
|
4
|
+
const value = inject(key);
|
|
5
|
+
if (value == null) throw new Error(`[Ropav] <${componentName}> must be used inside its parent provider component.`);
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { useRequiredInject as t };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=useRequiredInject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRequiredInject.js","names":[],"sources":["../src/composables/useRequiredInject.ts"],"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(`[Ropav] <${componentName}> must be used inside its parent provider component.`);\n }\n return value;\n}\n"],"mappings":";;AAEA,SAAgB,kBAAqB,KAAsB,eAA0B;CACjF,MAAM,QAAQ,OAAO,GAAG;CACxB,IAAI,SAAS,MACT,MAAM,IAAI,MAAM,YAAY,cAAc,qDAAqD;CAEnG,OAAO;AACX"}
|