@boobooking/dashboard-ui-components 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,196 @@
1
+ # @boobooking/dashboard-ui-components
2
+
3
+ Компоненты фильтров дашборда на Vue 3: телефон, поиск, выпадающий список,
4
+ интервал дат.
5
+
6
+ ## Установка
7
+
8
+ npm install @boobooking/dashboard-ui-components
9
+
10
+ ```js
11
+ import { RussianMobileFilter, SelectDateInterval } from '@boobooking/dashboard-ui-components'
12
+ import '@boobooking/dashboard-ui-components/style.css'
13
+ ```
14
+
15
+ Стили пакета подключаются **до** стилей приложения.
16
+
17
+ ## Требования
18
+
19
+ Vue не ниже 3.2, ESM, сборщик, умеющий импорт CSS из пакета.
20
+
21
+ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в CSS приложения
22
+ пакету не нужны.
23
+
24
+ ## Компоненты
25
+
26
+ Пакет экспортирует семь компонентов: `Popup`, `Dot`, `PickDay`,
27
+ `RussianMobileFilter`, `Search`, `SelectDateInterval`, `SelectSingle`. В
28
+ архив пакета (`files: ["dist"]`) исходники не попадают, поэтому контракт
29
+ каждого компонента — здесь и в playground, а не в исходном коде.
30
+
31
+ ### Popup
32
+
33
+ Всплывающее меню с оверлеем, закрывающим по клику вне, и переходом на
34
+ открытие/закрытие. `PickDay` и `SelectSingle` держат его внутри как обёртку
35
+ над своим содержимым.
36
+
37
+ <popup v-model:is-open="isOpen" align="right">
38
+ …содержимое меню…
39
+ </popup>
40
+
41
+ | Проп | Тип | По умолчанию | Описание |
42
+ | --- | --- | --- | --- |
43
+ | `isOpen` | `Boolean` | `false` | Открыто ли меню |
44
+ | `align` | `String` | `"left"` | `"left"` или `"right"` — с какой стороны прижать меню |
45
+
46
+ Событие: `update:isOpen` — при каждом открытии и закрытии, включая клик по
47
+ оверлею.
48
+
49
+ ### Dot
50
+
51
+ Индикатор-точка: красная или зелёная, с пульсацией или без.
52
+
53
+ <dot color="green" :add-pulse="isLive" />
54
+
55
+ | Проп | Тип | По умолчанию | Описание |
56
+ | --- | --- | --- | --- |
57
+ | `color` | `String` | обязателен | `"red"` или `"green"` |
58
+ | `addPulse` | `Boolean` | `false` | Добавляет анимацию пульсации |
59
+
60
+ Событий нет.
61
+
62
+ ### PickDay
63
+
64
+ Поле выбора одной даты на Pikaday, с ластиком очистки.
65
+
66
+ <pick-day v-model="date" placeholder-text="от" />
67
+
68
+ | Проп | Тип | По умолчанию | Описание |
69
+ | --- | --- | --- | --- |
70
+ | `modelValue` | `String` | обязателен | Текущая дата |
71
+ | `withEraser` | `Boolean` | `true` | Показывать ли ластик очистки |
72
+ | `placeholderText` | `String` | `""` | Текст подсказки в пустом поле |
73
+
74
+ События: `update:modelValue` — при выборе даты в календаре и при очистке
75
+ (пустой строкой); `changed` — в тех же двух случаях, для использования наравне
76
+ с остальными фильтрами.
77
+
78
+ ### RussianMobileFilter
79
+
80
+ Поле ввода российского мобильного номера с маской `+7 (000) 000 00 00` и
81
+ дебаунсом перед отправкой.
82
+
83
+ <russian-mobile-filter v-model="phone" header="Телефон" @changed="reload" />
84
+
85
+ | Проп | Тип | По умолчанию | Описание |
86
+ | --- | --- | --- | --- |
87
+ | `modelValue` | `String` | `""` | Номер: цифры вместе с кодом страны, без «+» (например, `79031234567`), либо пустая строка |
88
+ | `header` | `String` | обязателен | Подпись поля |
89
+ | `isRequired` | `Boolean` | `false` | Пометка обязательности в заголовке |
90
+ | `isLoading` | `Boolean` | `false` | Индикатор загрузки в заголовке |
91
+
92
+ «+» — неудачный символ для URL, поэтому в параметре только цифры; плюс к
93
+ номеру дописывает бэкенд.
94
+
95
+ События: `update:modelValue` — на каждое принятое маской изменение;
96
+ `changed` — через 400 мс паузы после ввода, начиная с третьей цифры (раньше
97
+ событие не летит вовсе), а также сразу — без дебаунса — при опустевшем поле,
98
+ по клику на ластик, по Enter и по уходу фокуса. Дублей не бывает: компонент
99
+ помнит последнее отправленное значение и не шлёт его повторно.
100
+
101
+ ### Search
102
+
103
+ Текстовое поле поиска с ластиком очистки.
104
+
105
+ <search v-model="query" header="Поиск" @changed="reload" />
106
+
107
+ | Проп | Тип | По умолчанию | Описание |
108
+ | --- | --- | --- | --- |
109
+ | `modelValue` | `String` | `""` | Текущий текст поиска |
110
+ | `header` | `String` | обязателен | Подпись поля |
111
+ | `isRequired` | `Boolean` | `false` | Пометка обязательности в заголовке |
112
+ | `isLoading` | `Boolean` | `false` | Индикатор загрузки в заголовке |
113
+
114
+ События: `update:modelValue` и `changed` — оба на каждый ввод.
115
+
116
+ ### SelectDateInterval
117
+
118
+ Пара `PickDay` под одним заголовком — интервал дат «от» и «до».
119
+
120
+ <select-date-interval
121
+ header="Период"
122
+ :date-from="dateFrom"
123
+ :date-to="dateTo"
124
+ @update:date-from="dateFrom = $event"
125
+ @update:date-to="dateTo = $event"
126
+ @changed="reload"
127
+ />
128
+
129
+ | Проп | Тип | По умолчанию | Описание |
130
+ | --- | --- | --- | --- |
131
+ | `dateFrom` | `String` | обязателен | Начало интервала |
132
+ | `dateTo` | `String` | обязателен | Конец интервала |
133
+ | `header` | `String` | обязателен | Подпись поля |
134
+ | `isRequired` | `Boolean` | `false` | Пометка обязательности в заголовке |
135
+ | `isLoading` | `Boolean` | `false` | Индикатор загрузки в заголовке |
136
+
137
+ `dateFrom` и `dateTo` обязательны без умолчания — потребитель должен
138
+ передавать обе даты явно.
139
+
140
+ События: `update:dateFrom`, `update:dateTo` — на каждый выбор в
141
+ соответствующем `PickDay`; `changed` — когда новое значение отличается от
142
+ переданного пропса (отдельно для каждой из двух дат).
143
+
144
+ ### SelectSingle
145
+
146
+ <select-single
147
+ header="Вендор"
148
+ :items="[{ id: 'a', name: 'Первый' }]"
149
+ v-model="vendor"
150
+ @changed="reload"
151
+ />
152
+
153
+ `items` — массив объектов `{ id, name }`. `v-model` держит `id` выбранного или
154
+ `null`, если не выбрано.
155
+
156
+ | Проп | Тип | По умолчанию | Описание |
157
+ | --- | --- | --- | --- |
158
+ | `items` | `Array` | обязателен | Массив `{ id, name }` |
159
+ | `modelValue` | `String \| Number` | `null` | `id` выбранного элемента или `null` |
160
+ | `header` | `String` | обязателен | Подпись поля |
161
+ | `isRequired` | `Boolean` | `false` | Пометка обязательности в заголовке |
162
+ | `isLoading` | `Boolean` | `false` | Индикатор загрузки в заголовке |
163
+
164
+ События: `update:modelValue` и `changed` — при выборе элемента (повторный
165
+ клик по уже выбранному снимает выбор) и при очистке через ластик.
166
+
167
+ ## Playground
168
+
169
+ npm run playground
170
+
171
+ Поднимает демо-страницы со всеми семью компонентами в двух окружениях:
172
+ голом (без Tailwind и стилей приложения) и в окружении приложения (с
173
+ Tailwind, `@tailwindcss/forms` и типографикой, как у потребителя). Это
174
+ основной способ посмотреть, как компоненты выглядят и ведут себя, а не
175
+ угадывать по исходникам или по этому README.
176
+
177
+ ## Что пакет берёт у приложения
178
+
179
+ Базовую типографику — семейство шрифта, размер, `line-height`. Он наследует её
180
+ намеренно, чтобы не навязывать свой шрифт дашборду с собственным. В приложении,
181
+ которое типографику не задаёт, компоненты отрисуются браузерными умолчаниями:
182
+ рабочими, но чужими на вид.
183
+
184
+ Компоненты русскоязычные: названия месяцев, подписи и правила номера телефона
185
+ зашиты.
186
+
187
+ ## Ограничение
188
+
189
+ Пакет отдаёт скомпилированные утилиты Tailwind — те же имена классов, что
190
+ генерирует Tailwind приложения. При стоковой палитре правила совпадают. Если
191
+ приложение переопределит стоковый цвет, одноимённые правила столкнутся и
192
+ победит подключённое позже, то есть компоненты возьмут палитру приложения.
193
+
194
+ Ресет пакета распространяется и на содержимое слотов — разметку приложения
195
+ внутри `Popup`. В приложении с preflight это ничего не меняет; без него
196
+ содержимое слота получит `box-sizing` и снятые границы.
package/dist/index.js ADDED
@@ -0,0 +1,794 @@
1
+ import { Fragment as e, Transition as t, createBlock as n, createCommentVNode as r, createElementBlock as i, createElementVNode as a, createVNode as o, mergeProps as s, normalizeClass as c, openBlock as l, renderList as u, renderSlot as d, resolveComponent as f, toDisplayString as p, vModelText as m, vShow as h, withCtx as g, withDirectives as _, withKeys as v, withModifiers as y } from "vue";
2
+ import ee from "pikaday";
3
+ import b from "imask";
4
+ //#region \0plugin-vue:export-helper
5
+ var x = (e, t) => {
6
+ let n = e.__vccOpts || e;
7
+ for (let [e, r] of t) n[e] = r;
8
+ return n;
9
+ }, S = {
10
+ props: {
11
+ isOpen: {
12
+ type: Boolean,
13
+ default: !1
14
+ },
15
+ isTransparent: {
16
+ type: Boolean,
17
+ default: !0
18
+ }
19
+ },
20
+ emits: ["update:isOpen", "escaped"],
21
+ methods: {
22
+ closeOverlay() {
23
+ this.$emit("update:isOpen", !1), this.$emit("escaped");
24
+ },
25
+ handleEscape(e) {
26
+ this.isOpen && (e.key === "Esc" || e.key === "Escape") && this.closeOverlay();
27
+ }
28
+ },
29
+ mounted() {
30
+ document.addEventListener("keydown", this.handleEscape);
31
+ },
32
+ beforeUnmount() {
33
+ document.removeEventListener("keydown", this.handleEscape);
34
+ }
35
+ };
36
+ function C(e, t, n, r, a, o) {
37
+ return _((l(), i("button", {
38
+ tabindex: "-1",
39
+ onClick: t[0] ||= y((...e) => o.closeOverlay && o.closeOverlay(...e), ["prevent"]),
40
+ class: c(["fixed inset-0 w-full h-full cursor-default flex items-start", {
41
+ "z-20": n.isOpen,
42
+ "bg-transparent": n.isTransparent,
43
+ "bg-gray-900 opacity-75": !n.isTransparent
44
+ }])
45
+ }, null, 2)), [[h, n.isOpen]]);
46
+ }
47
+ //#endregion
48
+ //#region src/components/Popup.vue
49
+ var w = {
50
+ components: { Overlay: /* @__PURE__ */ x(S, [["render", C]]) },
51
+ inheritAttrs: !1,
52
+ emits: ["update:isOpen"],
53
+ props: {
54
+ isOpen: {
55
+ type: Boolean,
56
+ default: !1
57
+ },
58
+ align: {
59
+ type: String,
60
+ default: "left"
61
+ }
62
+ },
63
+ data() {
64
+ return { overlayIsOpen: this.isOpen };
65
+ },
66
+ watch: {
67
+ isOpen: function(e) {
68
+ this.overlayIsOpen = e;
69
+ },
70
+ overlayIsOpen(e) {
71
+ this.$emit("update:isOpen", e);
72
+ }
73
+ },
74
+ computed: {
75
+ alignLeft() {
76
+ return this.align === "left";
77
+ },
78
+ alignRight() {
79
+ return this.align === "right";
80
+ }
81
+ }
82
+ }, T = { class: "bb-dashboard-ui relative" };
83
+ function E(e, n, r, c, u, p) {
84
+ let m = f("overlay");
85
+ return l(), i("div", T, [o(m, {
86
+ "is-open": u.overlayIsOpen,
87
+ "onUpdate:isOpen": n[0] ||= (e) => u.overlayIsOpen = e
88
+ }, null, 8, ["is-open"]), o(t, {
89
+ "enter-active-class": "transition ease-out duration-100",
90
+ "enter-from-class": "opacity-0 scale-95",
91
+ "enter-to-class": "opacity-100 scale-100",
92
+ "leave-active-class": "transition ease-in duration-75",
93
+ "leave-from-class": "opacity-100 scale-100",
94
+ "leave-to-class": "opacity-0 scale-95"
95
+ }, {
96
+ default: g(() => [_(a("div", s(e.$attrs, { class: ["absolute z-20", {
97
+ "left-0": p.alignLeft,
98
+ "right-0": p.alignRight
99
+ }] }), [d(e.$slots, "default")], 16), [[h, r.isOpen]])]),
100
+ _: 3
101
+ })]);
102
+ }
103
+ var D = /*#__PURE__*/ x(w, [["render", E]]), O = {
104
+ props: {
105
+ addPulse: {
106
+ type: Boolean,
107
+ default: !1
108
+ },
109
+ color: {
110
+ type: String,
111
+ required: !0,
112
+ validator: (e) => ["red", "green"].indexOf(e) !== -1
113
+ }
114
+ },
115
+ computed: {
116
+ isRed() {
117
+ return this.color === "red";
118
+ },
119
+ isGreen() {
120
+ return this.color === "green";
121
+ }
122
+ }
123
+ };
124
+ function te(e, t, n, r, o, s) {
125
+ return l(), i("div", { class: c(["bb-dashboard-ui flex h-full items-center leading-none text-4xl", {
126
+ "text-red-500": s.isRed,
127
+ "text-green-500": s.isGreen,
128
+ "animate-pulse": n.addPulse
129
+ }]) }, [...t[0] ||= [a("svg", {
130
+ class: "fill-current w-2 h-2",
131
+ viewBox: "0 0 120 120"
132
+ }, [a("circle", {
133
+ cx: "60",
134
+ cy: "60",
135
+ r: "45"
136
+ })], -1)]], 2);
137
+ }
138
+ var k = /*#__PURE__*/ x(O, [["render", te]]), A = {}, j = {
139
+ type: "button",
140
+ tabindex: "-1",
141
+ class: "absolute right-0 top-0 flex items-center justify-center bg-transparent cursor-pointer text-gray-300 hover:text-gray-400 focus:outline-hidden"
142
+ };
143
+ function M(e, t, n, r, o, s) {
144
+ return l(), i("button", j, [...t[0] ||= [a("svg", {
145
+ class: "w-6 h-6 stroke-current",
146
+ fill: "none",
147
+ viewBox: "0 0 24 24"
148
+ }, [a("path", {
149
+ "stroke-linecap": "round",
150
+ "stroke-linejoin": "round",
151
+ "stroke-width": "2",
152
+ d: "M6 18L18 6M6 6l12 12"
153
+ })], -1)]]);
154
+ }
155
+ var N = /*#__PURE__*/ x(A, [["render", M]]);
156
+ //#endregion
157
+ //#region src/date.js
158
+ function P(e) {
159
+ return `${String(e.getDate()).padStart(2, "0")}.${String(e.getMonth() + 1).padStart(2, "0")}.${String(e.getFullYear()).padStart(4, "0")}`;
160
+ }
161
+ function F(e) {
162
+ let t = /^(\d{1,2})\.(\d{1,2})\.(\d{4})$/.exec(e);
163
+ if (t === null) return null;
164
+ let [, n, r, i] = t.map(Number), a = /* @__PURE__ */ new Date(0);
165
+ return a.setFullYear(i, r - 1, n), a.setHours(0, 0, 0, 0), a.getDate() !== n || a.getMonth() !== r - 1 || a.getFullYear() !== i ? null : a;
166
+ }
167
+ //#endregion
168
+ //#region src/components/PickDay.vue
169
+ var I = {
170
+ components: {
171
+ Popup: D,
172
+ Eraser: N
173
+ },
174
+ emits: ["update:modelValue", "changed"],
175
+ props: {
176
+ modelValue: {
177
+ type: String,
178
+ required: !0
179
+ },
180
+ withEraser: {
181
+ type: Boolean,
182
+ default: !0
183
+ },
184
+ placeholderText: {
185
+ type: String,
186
+ default: ""
187
+ }
188
+ },
189
+ created() {
190
+ this.picker = null;
191
+ },
192
+ mounted() {
193
+ this.picker = new ee({
194
+ field: this.$refs.field,
195
+ container: this.$refs.container,
196
+ keyboardInput: !1,
197
+ bound: !1,
198
+ firstDay: 1,
199
+ parse: (e) => F(e),
200
+ toString: (e) => P(e),
201
+ i18n: {
202
+ previousMonth: "Предыдущий месяц",
203
+ nextMonth: "Следующий месяц",
204
+ months: [
205
+ "Январь",
206
+ "Февраль",
207
+ "Март",
208
+ "Апрель",
209
+ "Май",
210
+ "Июнь",
211
+ "Июль",
212
+ "Август",
213
+ "Сентябрь",
214
+ "Октябрь",
215
+ "Ноябрь",
216
+ "Декабрь"
217
+ ],
218
+ weekdays: [
219
+ "Воскресенье",
220
+ "Понедельник",
221
+ "Вторник",
222
+ "Среда",
223
+ "Четверг",
224
+ "Пятница",
225
+ "Суббота"
226
+ ],
227
+ weekdaysShort: [
228
+ "Вс",
229
+ "Пн",
230
+ "Вт",
231
+ "Ср",
232
+ "Чт",
233
+ "Пт",
234
+ "Сб"
235
+ ]
236
+ },
237
+ onSelect: (e) => {
238
+ this.popupIsOpen = !1, this.$emit("update:modelValue", P(e)), this.$emit("changed");
239
+ }
240
+ });
241
+ },
242
+ beforeUnmount() {
243
+ this.picker?.destroy();
244
+ },
245
+ data() {
246
+ return {
247
+ popupIsOpen: !1,
248
+ dayValue: this.modelValue
249
+ };
250
+ },
251
+ watch: { modelValue(e) {
252
+ this.dayValue = e, this.syncPicker(e);
253
+ } },
254
+ methods: {
255
+ syncPicker(e) {
256
+ let t = F(e);
257
+ if (t === null) {
258
+ this.picker.clear();
259
+ return;
260
+ }
261
+ this.picker.setDate(t, !0);
262
+ },
263
+ clearPicker() {
264
+ this.$emit("update:modelValue", ""), this.dayValue = "", this.picker.clear(), this.$emit("changed");
265
+ }
266
+ },
267
+ computed: {
268
+ hasValue() {
269
+ return this.modelValue.length > 0;
270
+ },
271
+ needsEraser() {
272
+ return !this.withEraser || this.popupIsOpen ? !1 : this.hasValue;
273
+ }
274
+ }
275
+ }, L = { class: "bb-dashboard-ui flex flex-col" }, R = { class: "relative flex h-full cursor-pointer leading-none" }, z = { class: "min-w-24 w-full h-full" }, B = [
276
+ "disabled",
277
+ "value",
278
+ "placeholder"
279
+ ], V = {
280
+ ref: "container",
281
+ class: "flex mt-1 bg-white border border-gray-200 rounded-md shadow-lg"
282
+ };
283
+ function H(e, t, s, u, d, p) {
284
+ let m = f("eraser"), h = f("popup");
285
+ return l(), i("div", L, [a("div", R, [a("button", {
286
+ ref: "trigger",
287
+ type: "button",
288
+ class: c(["flex w-full items-center focus:outline-hidden", { "z-20": d.popupIsOpen }]),
289
+ onClick: t[0] ||= (e) => d.popupIsOpen = !d.popupIsOpen
290
+ }, [a("label", z, [a("input", {
291
+ disabled: d.popupIsOpen,
292
+ ref: "field",
293
+ type: "text",
294
+ value: d.dayValue,
295
+ placeholder: s.placeholderText,
296
+ class: "w-full h-full py-2 pr-3 leading-none border border-transparent whitespace-nowrap bg-transparent placeholder:text-sm placeholder-gray-300 cursor-pointer focus:outline-hidden"
297
+ }, null, 8, B)])], 2), p.needsEraser ? (l(), n(m, {
298
+ key: 0,
299
+ onClick: p.clearPicker,
300
+ class: "z-10 h-full pr-2"
301
+ }, null, 8, ["onClick"])) : r("", !0)]), o(h, {
302
+ "is-open": d.popupIsOpen,
303
+ "onUpdate:isOpen": t[1] ||= (e) => d.popupIsOpen = e
304
+ }, {
305
+ default: g(() => [a("div", V, null, 512)]),
306
+ _: 1
307
+ }, 8, ["is-open"])]);
308
+ }
309
+ var U = /*#__PURE__*/ x(I, [["render", H]]), W = {
310
+ components: { Dot: k },
311
+ props: {
312
+ text: {
313
+ type: String,
314
+ required: !0
315
+ },
316
+ isRequired: {
317
+ type: Boolean,
318
+ default: !1
319
+ },
320
+ isLoading: {
321
+ type: Boolean,
322
+ default: !1
323
+ }
324
+ }
325
+ }, G = { class: "flex h-6 px-3 bg-white items-center justify-between" }, K = ["textContent"];
326
+ function q(e, t, n, r, s, c) {
327
+ let u = f("dot");
328
+ return l(), i("div", G, [
329
+ a("div", {
330
+ class: "flex flex-1 h-full items-center text-xs text-gray-500 whitespace-nowrap truncate leading-tight select-none",
331
+ textContent: p(n.text)
332
+ }, null, 8, K),
333
+ _(o(u, {
334
+ color: "red",
335
+ "add-pulse": !0,
336
+ class: "ml-3"
337
+ }, null, 512), [[h, n.isLoading]]),
338
+ _(o(u, {
339
+ color: "red",
340
+ class: "ml-3"
341
+ }, null, 512), [[h, n.isRequired]])
342
+ ]);
343
+ }
344
+ var J = /*#__PURE__*/ x(W, [["render", q]]), Y = 10;
345
+ function X(e) {
346
+ let t = e.replace(/\D/g, "");
347
+ return (t.startsWith("7") || t.startsWith("8")) && t[1] === "9" && (t = t.slice(1)), t.slice(0, Y);
348
+ }
349
+ function Z(e) {
350
+ return e === "" ? "" : `7${e}`;
351
+ }
352
+ function Q(e) {
353
+ let t = e.startsWith("+") ? e.slice(1) : e;
354
+ return t.startsWith("7") ? t.slice(1) : t;
355
+ }
356
+ //#endregion
357
+ //#region src/components/RussianMobileFilter.vue
358
+ var ne = 400, re = 3, ie = {
359
+ components: {
360
+ ElementHeader: J,
361
+ Eraser: N
362
+ },
363
+ emits: ["update:modelValue", "changed"],
364
+ props: {
365
+ modelValue: {
366
+ type: String,
367
+ default: ""
368
+ },
369
+ header: {
370
+ type: String,
371
+ required: !0
372
+ },
373
+ isRequired: {
374
+ type: Boolean,
375
+ default: !1
376
+ },
377
+ isLoading: {
378
+ type: Boolean,
379
+ default: !1
380
+ }
381
+ },
382
+ data() {
383
+ return { digits: Q(this.modelValue) };
384
+ },
385
+ created() {
386
+ this.mask = null, this.debounceTimer = null, this.isWritingProgrammatically = !1, this.lastCommitted = Q(this.modelValue);
387
+ },
388
+ mounted() {
389
+ this.mask = b(this.$refs.input, {
390
+ mask: "+7 (000) 000 00 00",
391
+ lazy: !0,
392
+ prepare: (e, t) => t.unmaskedValue === "" && (e === "7" || e === "8") ? "" : e
393
+ }), this.mask.on("accept", () => {
394
+ this.isWritingProgrammatically || (this.digits = this.mask.unmaskedValue, this.$emit("update:modelValue", Z(this.digits)), this.scheduleCommit());
395
+ }), this.syncFromModelValue(this.modelValue);
396
+ },
397
+ beforeUnmount() {
398
+ clearTimeout(this.debounceTimer), this.mask?.destroy();
399
+ },
400
+ watch: { modelValue(e) {
401
+ e !== Z(this.digits) && this.syncFromModelValue(e);
402
+ } },
403
+ methods: {
404
+ syncFromModelValue(e) {
405
+ this.writeToMask(Q(e)), this.digits = this.mask.unmaskedValue, this.lastCommitted = this.digits;
406
+ },
407
+ applyUserDigits(e) {
408
+ this.writeToMask(e), this.digits = this.mask.unmaskedValue, this.$emit("update:modelValue", Z(this.digits));
409
+ },
410
+ writeToMask(e) {
411
+ if (this.isWritingProgrammatically = !0, e === "") this.mask.value = "";
412
+ else {
413
+ let t = this.mask.masked.lazy;
414
+ this.mask.updateOptions({ lazy: !1 }), this.mask.unmaskedValue = e, this.mask.updateOptions({ lazy: t });
415
+ }
416
+ this.isWritingProgrammatically = !1;
417
+ },
418
+ setLazy(e) {
419
+ this.isWritingProgrammatically = !0, this.mask.updateOptions({ lazy: e }), this.isWritingProgrammatically = !1;
420
+ },
421
+ onFocus() {
422
+ this.setLazy(!1), this.$nextTick(() => {
423
+ let e = this.$refs.input.value.indexOf("_");
424
+ e !== -1 && this.$refs.input.setSelectionRange(e, e);
425
+ });
426
+ },
427
+ onBlur() {
428
+ this.setLazy(!0), this.digits === "" && this.writeToMask(""), this.commit();
429
+ },
430
+ onPaste(e) {
431
+ this.applyUserDigits(X(e.clipboardData?.getData("text") ?? "")), this.scheduleCommit();
432
+ },
433
+ clear() {
434
+ this.applyUserDigits(""), this.commit();
435
+ },
436
+ scheduleCommit() {
437
+ if (clearTimeout(this.debounceTimer), this.digits.length === 0) {
438
+ this.commit();
439
+ return;
440
+ }
441
+ this.digits.length < re || (this.debounceTimer = setTimeout(() => this.commit(), ne));
442
+ },
443
+ commit() {
444
+ clearTimeout(this.debounceTimer), this.digits !== this.lastCommitted && (this.lastCommitted = this.digits, this.$emit("changed"));
445
+ }
446
+ }
447
+ }, ae = { class: "bb-dashboard-ui flex flex-none" }, oe = { class: "flex w-full flex-col border border-white bg-white" }, se = { class: "relative flex h-full w-full" }, ce = { class: "flex w-full h-full items-center justify-center" };
448
+ function le(e, t, n, r, s, c) {
449
+ let u = f("element-header"), d = f("eraser");
450
+ return l(), i("div", ae, [a("div", oe, [o(u, {
451
+ text: n.header,
452
+ "is-required": n.isRequired,
453
+ "is-loading": n.isLoading
454
+ }, null, 8, [
455
+ "text",
456
+ "is-required",
457
+ "is-loading"
458
+ ]), a("div", se, [a("label", ce, [a("input", {
459
+ ref: "input",
460
+ type: "tel",
461
+ inputmode: "tel",
462
+ autocomplete: "off",
463
+ class: "flex w-phone h-full px-3 py-2 cursor-pointer truncate hover:bg-blue-100 focus:bg-white focus:outline-hidden border-none",
464
+ onFocus: t[0] ||= (...e) => c.onFocus && c.onFocus(...e),
465
+ onBlur: t[1] ||= (...e) => c.onBlur && c.onBlur(...e),
466
+ onKeydown: t[2] ||= v((...e) => c.commit && c.commit(...e), ["enter"]),
467
+ onPaste: t[3] ||= y((...e) => c.onPaste && c.onPaste(...e), ["prevent"])
468
+ }, null, 544), _(o(d, {
469
+ onMousedown: t[4] ||= y(() => {}, ["prevent"]),
470
+ onClick: c.clear,
471
+ class: "pr-2 h-full"
472
+ }, null, 8, ["onClick"]), [[h, s.digits.length > 0]])])])])]);
473
+ }
474
+ var ue = /*#__PURE__*/ x(ie, [["render", le]]), de = {
475
+ components: {
476
+ ElementHeader: J,
477
+ Eraser: N
478
+ },
479
+ emits: ["update:modelValue", "changed"],
480
+ props: {
481
+ modelValue: {
482
+ type: String,
483
+ default: ""
484
+ },
485
+ header: {
486
+ type: String,
487
+ required: !0
488
+ },
489
+ isRequired: {
490
+ type: Boolean,
491
+ default: !1
492
+ },
493
+ isLoading: {
494
+ type: Boolean,
495
+ default: !1
496
+ }
497
+ },
498
+ data() {
499
+ return { search: this.modelValue };
500
+ },
501
+ computed: { inputNeedsEraser() {
502
+ return this.search.length > 0;
503
+ } },
504
+ watch: {},
505
+ methods: {
506
+ clearInput() {
507
+ this.search = "", this.startSearch();
508
+ },
509
+ startSearch() {
510
+ this.$emit("update:modelValue", this.search), this.$emit("changed");
511
+ }
512
+ }
513
+ }, fe = { class: "bb-dashboard-ui flex flex-none" }, pe = { class: "flex w-full flex-col border border-white bg-white" }, me = { class: "relative flex h-full w-full" }, he = { class: "flex w-full h-full items-center justify-center" };
514
+ function ge(e, t, n, r, s, c) {
515
+ let u = f("element-header"), d = f("eraser");
516
+ return l(), i("div", fe, [a("div", pe, [o(u, {
517
+ text: n.header,
518
+ "is-required": n.isRequired,
519
+ "is-loading": n.isLoading
520
+ }, null, 8, [
521
+ "text",
522
+ "is-required",
523
+ "is-loading"
524
+ ]), a("div", me, [a("label", he, [_(a("input", {
525
+ class: "flex w-full h-full px-3 py-2 cursor-pointer truncate hover:bg-blue-100 focus:bg-white focus:outline-hidden border-none",
526
+ "onUpdate:modelValue": t[0] ||= (e) => s.search = e,
527
+ onInput: t[1] ||= (...e) => c.startSearch && c.startSearch(...e)
528
+ }, null, 544), [[
529
+ m,
530
+ s.search,
531
+ void 0,
532
+ { trim: !0 }
533
+ ]]), _(o(d, {
534
+ onClick: c.clearInput,
535
+ class: "pr-2 h-full"
536
+ }, null, 8, ["onClick"]), [[h, c.inputNeedsEraser]])])])])]);
537
+ }
538
+ var _e = /*#__PURE__*/ x(de, [["render", ge]]), ve = {
539
+ components: {
540
+ ElementHeader: J,
541
+ PickDay: U
542
+ },
543
+ emits: [
544
+ "update:dateFrom",
545
+ "update:dateTo",
546
+ "changed"
547
+ ],
548
+ props: {
549
+ dateFrom: {
550
+ type: String,
551
+ required: !0
552
+ },
553
+ dateTo: {
554
+ type: String,
555
+ required: !0
556
+ },
557
+ header: {
558
+ type: String,
559
+ required: !0
560
+ },
561
+ isRequired: {
562
+ type: Boolean,
563
+ default: !1
564
+ },
565
+ isLoading: {
566
+ type: Boolean,
567
+ default: !1
568
+ }
569
+ },
570
+ data() {
571
+ return {
572
+ userDateFrom: this.dateFrom,
573
+ userDateTo: this.dateTo
574
+ };
575
+ },
576
+ watch: {
577
+ dateFrom(e) {
578
+ this.userDateFrom = e;
579
+ },
580
+ dateTo(e) {
581
+ this.userDateTo = e;
582
+ },
583
+ userDateFrom(e) {
584
+ this.$emit("update:dateFrom", e), this.dateFrom !== e && this.$emit("changed");
585
+ },
586
+ userDateTo(e) {
587
+ this.$emit("update:dateTo", e), this.dateTo !== e && this.$emit("changed");
588
+ }
589
+ }
590
+ }, ye = { class: "bb-dashboard-ui flex" }, be = { class: "flex border border-white" }, xe = { class: "flex flex-col min-w-72 w-72 bg-white h-full" }, Se = { class: "flex h-full divide-x divide-gray-200" };
591
+ function Ce(e, t, n, r, s, c) {
592
+ let u = f("element-header"), d = f("pick-day");
593
+ return l(), i("div", ye, [a("div", be, [a("div", xe, [o(u, {
594
+ text: n.header,
595
+ "is-required": n.isRequired,
596
+ "is-loading": n.isLoading
597
+ }, null, 8, [
598
+ "text",
599
+ "is-required",
600
+ "is-loading"
601
+ ]), a("div", Se, [o(d, {
602
+ modelValue: s.userDateFrom,
603
+ "onUpdate:modelValue": t[0] ||= (e) => s.userDateFrom = e,
604
+ class: "flex-1 min-w-36 pl-3",
605
+ "placeholder-text": "от"
606
+ }, null, 8, ["modelValue"]), o(d, {
607
+ modelValue: s.userDateTo,
608
+ "onUpdate:modelValue": t[1] ||= (e) => s.userDateTo = e,
609
+ class: "flex-1 min-w-36 pl-3",
610
+ "placeholder-text": "до"
611
+ }, null, 8, ["modelValue"])])])])]);
612
+ }
613
+ var we = /*#__PURE__*/ x(ve, [["render", Ce]]), Te = {
614
+ components: {
615
+ Popup: D,
616
+ Eraser: N
617
+ },
618
+ emits: ["update:isOpen", "erased"],
619
+ props: {
620
+ isOpen: {
621
+ type: Boolean,
622
+ default: !1
623
+ },
624
+ title: {
625
+ type: String,
626
+ default: null
627
+ },
628
+ hasValue: {
629
+ type: Boolean,
630
+ default: !0
631
+ }
632
+ },
633
+ data() {
634
+ return { popupIsOpen: this.isOpen };
635
+ },
636
+ watch: {
637
+ isOpen(e) {
638
+ this.popupIsOpen = e;
639
+ },
640
+ popupIsOpen(e) {
641
+ this.$emit("update:isOpen", e);
642
+ }
643
+ },
644
+ computed: { needsEraser() {
645
+ return !this.isOpen && this.hasValue;
646
+ } }
647
+ }, Ee = { class: "flex flex-col grow bg-white" }, De = { class: "relative flex w-full h-full" }, $ = ["textContent"];
648
+ function Oe(e, t, s, u, m, h) {
649
+ let _ = f("eraser"), v = f("popup");
650
+ return l(), i("div", Ee, [a("div", De, [a("button", {
651
+ type: "button",
652
+ class: c(["flex w-full h-full items-center focus:outline-hidden cursor-pointer", { "z-20": s.isOpen }]),
653
+ onClick: t[0] ||= y((t) => e.$emit("update:isOpen", !s.isOpen), ["prevent"])
654
+ }, [a("span", {
655
+ class: "flex w-full h-full pl-3 pr-12 py-2 items-center whitespace-nowrap leading-none",
656
+ textContent: p(s.title)
657
+ }, null, 8, $)], 2), h.needsEraser ? (l(), n(_, {
658
+ key: 0,
659
+ onClick: t[1] ||= (t) => e.$emit("erased"),
660
+ class: "pr-2 h-full"
661
+ })) : r("", !0)]), o(v, {
662
+ "is-open": m.popupIsOpen,
663
+ "onUpdate:isOpen": t[2] ||= (e) => m.popupIsOpen = e
664
+ }, {
665
+ default: g(() => [d(e.$slots, "default")]),
666
+ _: 3
667
+ }, 8, ["is-open"])]);
668
+ }
669
+ var ke = /*#__PURE__*/ x(Te, [["render", Oe]]), Ae = {
670
+ props: {
671
+ isChecked: {
672
+ type: Boolean,
673
+ default: !1
674
+ },
675
+ name: { type: String }
676
+ },
677
+ emits: ["clicked"],
678
+ methods: { toggle() {
679
+ this.$emit("clicked");
680
+ } }
681
+ }, je = { class: "flex w-9 h-9 items-center justify-center" }, Me = {
682
+ class: "w-5 h-5 fill-current text-green-300",
683
+ viewBox: "0 0 20 20"
684
+ }, Ne = ["textContent"];
685
+ function Pe(e, t, n, r, o, s) {
686
+ return l(), i("button", {
687
+ type: "button",
688
+ onClick: t[0] ||= y((...e) => s.toggle && s.toggle(...e), ["prevent"]),
689
+ class: "flex w-full bg-white hover:bg-indigo-100 cursor-pointer focus:outline-hidden focus:ring-3 focus:z-10 focus:ring-blue-500/50"
690
+ }, [a("span", je, [_((l(), i("svg", Me, [...t[1] ||= [a("path", {
691
+ d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z",
692
+ "clip-rule": "evenodd",
693
+ "fill-rule": "evenodd"
694
+ }, null, -1)]], 512)), [[h, n.isChecked]])]), a("span", {
695
+ class: "flex h-9 justify-center items-center pr-6 whitespace-nowrap select-none",
696
+ textContent: p(n.name)
697
+ }, null, 8, Ne)]);
698
+ }
699
+ //#endregion
700
+ //#region src/components/SelectSingle.vue
701
+ var Fe = {
702
+ components: {
703
+ ElementHeader: J,
704
+ DropdownButton: ke,
705
+ ListElement: /* @__PURE__ */ x(Ae, [["render", Pe]])
706
+ },
707
+ emits: ["update:modelValue", "changed"],
708
+ props: {
709
+ items: {
710
+ type: Array,
711
+ required: !0
712
+ },
713
+ modelValue: {
714
+ type: [String, Number],
715
+ default: null
716
+ },
717
+ header: {
718
+ type: String,
719
+ required: !0
720
+ },
721
+ isRequired: {
722
+ type: Boolean,
723
+ default: !1
724
+ },
725
+ isLoading: {
726
+ type: Boolean,
727
+ default: !1
728
+ }
729
+ },
730
+ data() {
731
+ return { isOpen: !1 };
732
+ },
733
+ computed: {
734
+ activeItem() {
735
+ return this.items.find((e) => e.id === this.modelValue) ?? null;
736
+ },
737
+ activeItemName() {
738
+ return this.activeItem === null ? null : this.activeItem.name;
739
+ },
740
+ hasItems() {
741
+ return this.items.length > 0;
742
+ },
743
+ hasValue() {
744
+ return this.activeItem !== null;
745
+ }
746
+ },
747
+ methods: {
748
+ itemClicked(e) {
749
+ this.isOpen = !1, this.$emit("update:modelValue", e.id === this.modelValue ? null : e.id), this.$emit("changed");
750
+ },
751
+ clear() {
752
+ this.$emit("update:modelValue", null), this.$emit("changed");
753
+ }
754
+ }
755
+ }, Ie = { class: "bb-dashboard-ui flex flex-none" }, Le = { class: "flex w-full flex-col border border-white bg-white" }, Re = { class: "flex flex-col py-1 mt-1 bg-white border border-gray-200 rounded-md shadow-lg divide-y divide-gray-200 divide-dashed" };
756
+ function ze(t, s, c, d, p, m) {
757
+ let h = f("element-header"), _ = f("list-element"), v = f("dropdown-button");
758
+ return l(), i("div", Ie, [a("div", Le, [o(h, {
759
+ text: c.header,
760
+ "is-required": c.isRequired,
761
+ "is-loading": c.isLoading
762
+ }, null, 8, [
763
+ "text",
764
+ "is-required",
765
+ "is-loading"
766
+ ]), m.hasItems ? (l(), n(v, {
767
+ key: 0,
768
+ title: m.activeItemName,
769
+ "is-open": p.isOpen,
770
+ "onUpdate:isOpen": s[0] ||= (e) => p.isOpen = e,
771
+ "has-value": m.hasValue,
772
+ onErased: m.clear
773
+ }, {
774
+ default: g(() => [a("div", Re, [(l(!0), i(e, null, u(c.items, (e) => (l(), n(_, {
775
+ name: e.name,
776
+ key: e.id,
777
+ "is-checked": e.id === c.modelValue,
778
+ onClicked: (t) => m.itemClicked(e)
779
+ }, null, 8, [
780
+ "name",
781
+ "is-checked",
782
+ "onClicked"
783
+ ]))), 128))])]),
784
+ _: 1
785
+ }, 8, [
786
+ "title",
787
+ "is-open",
788
+ "has-value",
789
+ "onErased"
790
+ ])) : r("", !0)])]);
791
+ }
792
+ var Be = /*#__PURE__*/ x(Fe, [["render", ze]]);
793
+ //#endregion
794
+ export { k as Dot, U as PickDay, D as Popup, ue as RussianMobileFilter, _e as Search, we as SelectDateInterval, Be as SelectSingle };
package/dist/style.css ADDED
@@ -0,0 +1,2 @@
1
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-divide-x-reverse:0;--tw-border-style:solid;--tw-divide-y-reverse:0;--tw-leading:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--color-red-500:oklch(63.7% .237 25.331);--color-green-300:oklch(87.1% .15 154.449);--color-green-500:oklch(72.3% .219 149.579);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-500:oklch(62.3% .214 259.815);--color-indigo-100:oklch(93% .034 272.788);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-900:oklch(21% .034 264.665);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--leading-tight:1.25;--radius-md:.375rem;--ease-in:cubic-bezier(.4, 0, 1, 1);--ease-out:cubic-bezier(0, 0, .2, 1);--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--container-phone:calc(19ch + 16px)}}@layer base;@layer components{.bb-dashboard-ui,.bb-dashboard-ui *,.bb-dashboard-ui :before,.bb-dashboard-ui :after{box-sizing:border-box;border:0 solid;margin:0;padding:0}.bb-dashboard-ui button,.bb-dashboard-ui input{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}.bb-dashboard-ui button{appearance:button}.bb-dashboard-ui input{appearance:none}.bb-dashboard-ui input:focus{box-shadow:none}.bb-dashboard-ui ::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){.bb-dashboard-ui ::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}.bb-dashboard-ui ::placeholder{opacity:1}}@layer utilities{.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:0}.top-0{top:0}.right-0{right:0}.left-0{left:0}.z-10{z-index:10}.z-20{z-index:20}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mt-1{margin-top:var(--spacing)}.ml-3{margin-left:calc(var(--spacing) * 3)}.block{display:block}.flex{display:flex}.h-2{height:calc(var(--spacing) * 2)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-9{height:calc(var(--spacing) * 9)}.h-full{height:100%}.w-2{width:calc(var(--spacing) * 2)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-9{width:calc(var(--spacing) * 9)}.w-72{width:calc(var(--spacing) * 72)}.w-full{width:100%}.w-phone{width:var(--container-phone)}.min-w-24{min-width:calc(var(--spacing) * 24)}.min-w-36{min-width:calc(var(--spacing) * 36)}.min-w-72{min-width:calc(var(--spacing) * 72)}.flex-1{flex:1}.flex-none{flex:none}.grow{flex-grow:1}.origin-top-right{transform-origin:100% 0}.scale-95{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x) var(--tw-scale-y)}.scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x) var(--tw-scale-y)}.animate-pulse{animation:var(--animate-pulse)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}:where(.divide-x>:not(:last-child)){--tw-divide-x-reverse:0;border-inline-style:var(--tw-border-style);border-inline-start-width:calc(1px * var(--tw-divide-x-reverse));border-inline-end-width:calc(1px * calc(1 - var(--tw-divide-x-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-dashed>:not(:last-child)){--tw-border-style:dashed;border-style:dashed}:where(.divide-gray-200>:not(:last-child)){border-color:var(--color-gray-200)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-none{--tw-border-style:none;border-style:none}.border-gray-200{border-color:var(--color-gray-200)}.border-transparent{border-color:#0000}.border-white{border-color:var(--color-white)}.bg-gray-900{background-color:var(--color-gray-900)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.fill-current{fill:currentColor}.stroke-current{stroke:currentColor}.px-3{padding-inline:calc(var(--spacing) * 3)}.py-1{padding-block:var(--spacing)}.py-2{padding-block:calc(var(--spacing) * 2)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pr-6{padding-right:calc(var(--spacing) * 6)}.pr-12{padding-right:calc(var(--spacing) * 12)}.pl-3{padding-left:calc(var(--spacing) * 3)}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.whitespace-nowrap{white-space:nowrap}.text-gray-300{color:var(--color-gray-300)}.text-gray-500{color:var(--color-gray-500)}.text-green-300{color:var(--color-green-300)}.text-green-500{color:var(--color-green-500)}.text-red-500{color:var(--color-red-500)}.placeholder-gray-300::placeholder{color:var(--color-gray-300)}.opacity-0{opacity:0}.opacity-75{opacity:.75}.opacity-100{opacity:1}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-75{--tw-duration:75ms;transition-duration:75ms}.duration-100{--tw-duration:.1s;transition-duration:.1s}.ease-in{--tw-ease:var(--ease-in);transition-timing-function:var(--ease-in)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-none{-webkit-user-select:none;user-select:none}.placeholder\:text-sm::placeholder{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}@media (hover:hover){.hover\:bg-blue-100:hover{background-color:var(--color-blue-100)}.hover\:bg-indigo-100:hover{background-color:var(--color-indigo-100)}.hover\:text-gray-400:hover{color:var(--color-gray-400)}}.focus\:z-10:focus{z-index:10}.focus\:bg-white:focus{background-color:var(--color-white)}.focus\:ring-3:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-blue-500\/50:focus{--tw-ring-color:#3080ff80}@supports (color:color-mix(in lab, red, red)){.focus\:ring-blue-500\/50:focus{--tw-ring-color:color-mix(in oklab, var(--color-blue-500) 50%, transparent)}}.focus\:outline-hidden:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.focus\:outline-hidden:focus{outline-offset:2px;outline:2px solid #0000}}}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-divide-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-leading{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}.pika-single{z-index:9999;color:#333;background:#fff;border:1px solid #ccc;border-bottom-color:#bbb;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;display:block;position:relative}.pika-single:before,.pika-single:after{content:" ";display:table}.pika-single:after{clear:both}.pika-single.is-hidden{display:none}.pika-single.is-bound{position:absolute;box-shadow:0 5px 15px -5px #00000080}.pika-lendar{float:left;width:240px;margin:8px}.pika-title{text-align:center;position:relative}.pika-label{z-index:9999;background-color:#fff;margin:0;padding:5px 3px;font-size:14px;font-weight:700;line-height:20px;display:inline-block;position:relative;overflow:hidden}.pika-title select{cursor:pointer;z-index:9998;opacity:0;margin:0;position:absolute;top:5px;left:0}.pika-prev,.pika-next{cursor:pointer;text-indent:20px;white-space:nowrap;opacity:.5;background-color:#0000;background-position:50%;background-repeat:no-repeat;background-size:75% 75%;border:0;outline:none;width:20px;height:30px;padding:0;display:block;position:relative;overflow:hidden}.pika-prev:hover,.pika-next:hover{opacity:1}.pika-prev,.is-rtl .pika-next{float:left;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg==)}.pika-next,.is-rtl .pika-prev{float:right;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII=)}.pika-prev.is-disabled,.pika-next.is-disabled{cursor:default;opacity:.2}.pika-select{display:inline-block}.pika-table{border-collapse:collapse;border-spacing:0;border:0;width:100%}.pika-table th,.pika-table td{width:14.2857%;padding:0}.pika-table th{color:#999;text-align:center;font-size:12px;font-weight:700;line-height:25px}.pika-button{cursor:pointer;box-sizing:border-box;color:#666;text-align:right;width:100%;height:initial;background:#f5f5f5;border:0;outline:none;margin:0;padding:5px;font-size:12px;line-height:15px;display:block}.pika-week{color:#999;font-size:11px}.is-today .pika-button{color:#3af;font-weight:700}.is-selected .pika-button,.has-event .pika-button{color:#fff;background:#3af;border-radius:3px;font-weight:700;box-shadow:inset 0 1px 3px #178fe5}.has-event .pika-button{background:#005da9;box-shadow:inset 0 1px 3px #0076c9}.is-disabled .pika-button,.is-inrange .pika-button{background:#d5e9f7}.is-startrange .pika-button{color:#fff;box-shadow:none;background:#6cb31d;border-radius:3px}.is-endrange .pika-button{color:#fff;box-shadow:none;background:#3af;border-radius:3px}.is-disabled .pika-button{pointer-events:none;cursor:default;color:#999;opacity:.3}.is-outside-current-month .pika-button{color:#999;opacity:.3}.is-selection-disabled{pointer-events:none;cursor:default}.pika-button:hover,.pika-row.pick-whole-week:hover .pika-button{color:#fff;box-shadow:none;background:#ff8000;border-radius:3px}.pika-table abbr{cursor:help;border-bottom:none}
2
+ /*$vite$:1*/
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@boobooking/dashboard-ui-components",
3
+ "version": "0.1.0",
4
+ "description": "Компоненты фильтров дашборда на Vue 3",
5
+ "keywords": [
6
+ "vue",
7
+ "vue3",
8
+ "components",
9
+ "dashboard",
10
+ "filters",
11
+ "tailwind"
12
+ ],
13
+ "license": "MIT",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/boobooking/dashboard-ui-components.git"
17
+ },
18
+ "type": "module",
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "exports": {
23
+ ".": "./dist/index.js",
24
+ "./style.css": "./dist/style.css",
25
+ "./package.json": "./package.json"
26
+ },
27
+ "scripts": {
28
+ "build": "vite build",
29
+ "test": "vitest run --passWithNoTests",
30
+ "playground": "npm run build && vite --config vite.playground.config.js"
31
+ },
32
+ "peerDependencies": {
33
+ "vue": "^3.2"
34
+ },
35
+ "dependencies": {
36
+ "imask": "^7.6.1",
37
+ "pikaday": "^1.8.2"
38
+ },
39
+ "devDependencies": {
40
+ "@tailwindcss/forms": "^0.5.10",
41
+ "@tailwindcss/vite": "^4.3.3",
42
+ "@vitejs/plugin-vue": "^6.0.8",
43
+ "tailwindcss": "^4.3.3",
44
+ "vite": "^8.3.0",
45
+ "vitest": "^5.0.0",
46
+ "vue": "^3.5.35"
47
+ }
48
+ }