@shifl-inc/ui 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.
@@ -0,0 +1,685 @@
1
+ import {
2
+ ref as C,
3
+ computed as k,
4
+ defineComponent as O,
5
+ createElementBlock as p,
6
+ openBlock as b,
7
+ createElementVNode as n,
8
+ toDisplayString as _,
9
+ createTextVNode as U,
10
+ Fragment as $,
11
+ renderList as S,
12
+ withModifiers as N,
13
+ normalizeClass as j,
14
+ watch as V,
15
+ createBlock as H,
16
+ createCommentVNode as M,
17
+ unref as g,
18
+ normalizeStyle as R,
19
+ provide as Y,
20
+ inject as q,
21
+ onMounted as Q,
22
+ onUnmounted as X
23
+ } from 'vue';
24
+ function Z(e) {
25
+ const i = (e.columns || []).map((r) => ({
26
+ ...r,
27
+ frozen: r.frozen ?? r.fixed ?? !1,
28
+ visible: r.visible ?? !0
29
+ }));
30
+ return {
31
+ ...e,
32
+ columns: i,
33
+ rows: e.rows ?? [],
34
+ search: e.search ?? [],
35
+ filters: e.filters ?? [],
36
+ paginationMeta: e.paginationMeta ?? {}
37
+ };
38
+ }
39
+ function ee(e) {
40
+ const i = [...e],
41
+ r = C([...e]);
42
+ function c(o) {
43
+ r.value = r.value.map((t) => (t.key === o ? { ...t, visible: !t.visible } : t));
44
+ }
45
+ function l(o) {
46
+ r.value = r.value.map((t) => ({ ...t, visible: o }));
47
+ }
48
+ function f(o) {
49
+ const t = r.value.map((v) => (v.key === o ? { ...v, frozen: !v.frozen } : v)),
50
+ m = t.filter((v) => v.frozen),
51
+ y = t.filter((v) => !v.frozen);
52
+ r.value = [...m, ...y];
53
+ }
54
+ function h(o, t) {
55
+ if (o === t || t < 0 || t >= r.value.length) return;
56
+ const m = r.value.findIndex((G) => !G.frozen),
57
+ y = m === -1 ? r.value.length : m;
58
+ if (o < y || t < y) return;
59
+ const v = [...r.value],
60
+ [z] = v.splice(o, 1);
61
+ (v.splice(t, 0, z), (r.value = v));
62
+ }
63
+ function w() {
64
+ r.value = [...i];
65
+ }
66
+ const s = k(() => r.value.filter((o) => o.visible));
67
+ return {
68
+ columns: r,
69
+ visibleColumns: s,
70
+ toggleColumnVisibility: c,
71
+ setAllVisible: l,
72
+ toggleFrozen: f,
73
+ moveColumn: h,
74
+ resetColumns: w
75
+ };
76
+ }
77
+ function te(e) {
78
+ const i = C(e);
79
+ function r(l) {
80
+ var f;
81
+ i.value =
82
+ ((f = i.value) == null ? void 0 : f.key) === l && i.value.order === 'asc'
83
+ ? { key: l, order: 'desc' }
84
+ : { key: l, order: 'asc' };
85
+ }
86
+ function c(l) {
87
+ if (!i.value) return l;
88
+ const { key: f, order: h } = i.value;
89
+ return [...l].sort((w, s) => {
90
+ const o = w[f],
91
+ t = s[f];
92
+ if (o === t) return 0;
93
+ if (o == null) return 1;
94
+ if (t == null) return -1;
95
+ const m = String(o).localeCompare(String(t), void 0, {
96
+ numeric: !0
97
+ });
98
+ return h === 'asc' ? m : -m;
99
+ });
100
+ }
101
+ return {
102
+ sort: i,
103
+ setSort: r,
104
+ applySort: c
105
+ };
106
+ }
107
+ function ne() {
108
+ const e = C('');
109
+ function i(c) {
110
+ e.value = c;
111
+ }
112
+ function r(c, l) {
113
+ const f = e.value.trim().toLowerCase();
114
+ return f
115
+ ? c.filter((h) =>
116
+ (l && l.length ? l.map((s) => h[s]) : Object.values(h)).some((s) =>
117
+ String(s ?? '')
118
+ .toLowerCase()
119
+ .includes(f)
120
+ )
121
+ )
122
+ : c;
123
+ }
124
+ return {
125
+ globalFilter: e,
126
+ setGlobalFilter: i,
127
+ applyGlobalFilter: r
128
+ };
129
+ }
130
+ const oe = { class: 'fixed inset-0 z-40 flex justify-end bg-black/20' },
131
+ re = {
132
+ class: 'flex h-full w-full max-w-md flex-col bg-white shadow-xl ring-1 ring-black/5',
133
+ role: 'dialog',
134
+ 'aria-modal': 'true'
135
+ },
136
+ le = { class: 'flex items-center justify-between border-b border-gray-200 px-6 py-4' },
137
+ se = { class: 'min-w-0' },
138
+ ie = { class: 'text-xs font-medium text-gray-400' },
139
+ ue = { class: 'flex items-center justify-between border-b border-gray-200 px-6 py-3 text-xs' },
140
+ ae = { class: 'flex gap-3 font-medium text-gray-600' },
141
+ de = { class: 'flex-1 overflow-y-auto px-4 py-4' },
142
+ ce = { class: 'space-y-2' },
143
+ fe = ['draggable', 'onDragstart', 'onDragover', 'onDrop'],
144
+ ve = { class: 'flex items-center gap-3' },
145
+ ge = ['aria-label'],
146
+ be = { class: 'flex items-center gap-2' },
147
+ me = ['checked', 'onChange'],
148
+ pe = { class: 'text-gray-800' },
149
+ ye = { class: 'flex items-center gap-2 text-gray-400' },
150
+ he = ['onClick'],
151
+ xe = { class: 'flex justify-end gap-3 border-t border-gray-200 px-6 py-3' },
152
+ we = /* @__PURE__ */ O({
153
+ __name: 'GridColumnManager',
154
+ props: {
155
+ titlePrefix: {},
156
+ columns: {}
157
+ },
158
+ emits: [
159
+ 'close',
160
+ 'toggle',
161
+ 'move',
162
+ 'toggleFrozen',
163
+ 'selectAll',
164
+ 'deselectAll',
165
+ 'restoreDefault'
166
+ ],
167
+ setup(e, { emit: i }) {
168
+ const r = e,
169
+ c = i,
170
+ l = C(null);
171
+ function f(s) {
172
+ var o;
173
+ ((o = r.columns[s]) != null && o.frozen) || (l.value = s);
174
+ }
175
+ function h(s) {}
176
+ function w(s) {
177
+ l.value === null || l.value === s || (c('move', l.value, s), (l.value = null));
178
+ }
179
+ return (s, o) => (
180
+ b(),
181
+ p('div', oe, [
182
+ n('div', re, [
183
+ n('header', le, [
184
+ n('div', se, [
185
+ n('p', ie, _(e.titlePrefix), 1),
186
+ o[6] ||
187
+ (o[6] = n(
188
+ 'h2',
189
+ { class: 'truncate text-base font-semibold text-gray-900' },
190
+ ' Edit Columns ',
191
+ -1
192
+ ))
193
+ ]),
194
+ n(
195
+ 'button',
196
+ {
197
+ type: 'button',
198
+ class:
199
+ 'inline-flex h-8 w-8 items-center justify-center rounded-full text-gray-400 hover:bg-gray-100 hover:text-gray-600',
200
+ onClick: o[0] || (o[0] = (t) => s.$emit('close'))
201
+ },
202
+ [...(o[7] || (o[7] = [n('span', { class: 'sr-only' }, 'Close', -1), U(' ✕ ', -1)]))]
203
+ )
204
+ ]),
205
+ n('div', ue, [
206
+ n('div', ae, [
207
+ n(
208
+ 'button',
209
+ {
210
+ type: 'button',
211
+ class: 'hover:text-blue-600',
212
+ onClick: o[1] || (o[1] = (t) => s.$emit('selectAll'))
213
+ },
214
+ ' Select All '
215
+ ),
216
+ n(
217
+ 'button',
218
+ {
219
+ type: 'button',
220
+ class: 'hover:text-blue-600',
221
+ onClick: o[2] || (o[2] = (t) => s.$emit('deselectAll'))
222
+ },
223
+ ' Deselect All '
224
+ )
225
+ ]),
226
+ n(
227
+ 'button',
228
+ {
229
+ type: 'button',
230
+ class: 'text-xs font-medium text-blue-600 hover:text-blue-700',
231
+ onClick: o[3] || (o[3] = (t) => s.$emit('restoreDefault'))
232
+ },
233
+ ' Restore Default '
234
+ )
235
+ ]),
236
+ n('div', de, [
237
+ n('ul', ce, [
238
+ (b(!0),
239
+ p(
240
+ $,
241
+ null,
242
+ S(
243
+ e.columns,
244
+ (t, m) => (
245
+ b(),
246
+ p(
247
+ 'li',
248
+ {
249
+ key: t.key,
250
+ class:
251
+ 'flex items-center justify-between rounded-lg border border-gray-200 bg-gray-50 px-4 py-2 text-sm shadow-[0_1px_0_rgba(15,23,42,0.02)]',
252
+ draggable: !t.frozen,
253
+ onDragstart: (y) => f(m),
254
+ onDragover: N((y) => void 0, ['prevent']),
255
+ onDrop: N((y) => w(m), ['prevent'])
256
+ },
257
+ [
258
+ n('div', ve, [
259
+ n(
260
+ 'button',
261
+ {
262
+ type: 'button',
263
+ class: j([
264
+ 'cursor-grab text-gray-300 hover:text-gray-500',
265
+ { 'opacity-40 cursor-not-allowed': t.frozen }
266
+ ]),
267
+ 'aria-label': `Move ${t.label}`
268
+ },
269
+ ' ⋮⋮ ',
270
+ 10,
271
+ ge
272
+ ),
273
+ n('label', be, [
274
+ n(
275
+ 'input',
276
+ {
277
+ type: 'checkbox',
278
+ class:
279
+ 'h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500',
280
+ checked: t.visible,
281
+ onChange: (y) => s.$emit('toggle', t.key)
282
+ },
283
+ null,
284
+ 40,
285
+ me
286
+ ),
287
+ n('span', pe, _(t.label), 1)
288
+ ])
289
+ ]),
290
+ n('div', ye, [
291
+ n(
292
+ 'button',
293
+ {
294
+ type: 'button',
295
+ class: j([
296
+ 'h-7 w-7 rounded-full border border-transparent text-xs font-medium text-gray-500 hover:border-blue-200 hover:bg-blue-50 hover:text-blue-600 disabled:opacity-40',
297
+ {
298
+ 'bg-blue-50 text-blue-600 border-blue-200': t.frozen
299
+ }
300
+ ]),
301
+ onClick: (y) => s.$emit('toggleFrozen', t.key)
302
+ },
303
+ ' Pin ',
304
+ 10,
305
+ he
306
+ )
307
+ ])
308
+ ],
309
+ 40,
310
+ fe
311
+ )
312
+ )
313
+ ),
314
+ 128
315
+ ))
316
+ ])
317
+ ]),
318
+ n('footer', xe, [
319
+ n(
320
+ 'button',
321
+ {
322
+ type: 'button',
323
+ class:
324
+ 'rounded-md border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50',
325
+ onClick: o[4] || (o[4] = (t) => s.$emit('close'))
326
+ },
327
+ ' Cancel '
328
+ ),
329
+ n(
330
+ 'button',
331
+ {
332
+ type: 'button',
333
+ class:
334
+ 'rounded-md bg-blue-600 px-4 py-2 text-sm font-semibold text-white hover:bg-blue-700',
335
+ onClick: o[5] || (o[5] = (t) => s.$emit('close'))
336
+ },
337
+ ' Update '
338
+ )
339
+ ])
340
+ ])
341
+ ])
342
+ );
343
+ }
344
+ }),
345
+ _e = { class: 'shifl-grid relative' },
346
+ ke = { class: 'shifl-grid__controls' },
347
+ Ce = ['value'],
348
+ $e = { class: 'shifl-grid__header flex items-center justify-between' },
349
+ Se = { class: 'text-xs font-medium text-gray-500' },
350
+ ze = { class: 'shifl-grid__viewport' },
351
+ Ge = { class: 'shifl-grid__table' },
352
+ De = ['onClick'],
353
+ Fe = { key: 0 },
354
+ Ae = { key: 0 },
355
+ Me = ['colspan'],
356
+ Te = /* @__PURE__ */ O({
357
+ __name: 'ShiflGrid',
358
+ props: {
359
+ config: {}
360
+ },
361
+ setup(e) {
362
+ const i = e,
363
+ r = k(() => Z(i.config)),
364
+ {
365
+ columns: c,
366
+ visibleColumns: l,
367
+ toggleColumnVisibility: f,
368
+ setAllVisible: h,
369
+ toggleFrozen: w,
370
+ moveColumn: s,
371
+ resetColumns: o
372
+ } = ee(r.value.columns),
373
+ { sort: t, setSort: m, applySort: y } = te(r.value.sort),
374
+ { globalFilter: v, setGlobalFilter: z, applyGlobalFilter: G } = ne(),
375
+ D = C(!1);
376
+ (V(
377
+ () => r.value.columns,
378
+ (u) => {
379
+ c.value = [...u];
380
+ },
381
+ { deep: !0 }
382
+ ),
383
+ V(
384
+ () => r.value.sort,
385
+ (u) => {
386
+ u && (t.value = u);
387
+ },
388
+ { deep: !0 }
389
+ ));
390
+ const P = k(() => G(r.value.rows, r.value.search)),
391
+ F = k(() => y(P.value)),
392
+ K = k(() => {
393
+ let u = 0;
394
+ const a = {};
395
+ for (const d of l.value) {
396
+ d.frozen && (a[d.key] = u);
397
+ const x = parseInt(d.width ?? '160', 10);
398
+ Number.isNaN(x) || (u += x);
399
+ }
400
+ return a;
401
+ });
402
+ function W(u) {
403
+ const a = c.value.find((d) => d.key === u);
404
+ a != null && a.sortable && m(u);
405
+ }
406
+ function I(u) {
407
+ const a = u.target.value;
408
+ z(a);
409
+ }
410
+ function J(u) {
411
+ return u == null ? '' : typeof u == 'object' ? JSON.stringify(u) : String(u);
412
+ }
413
+ function E(u, a = !0) {
414
+ const d = {
415
+ width: u.width ?? '160px',
416
+ minWidth: u.width ?? '160px'
417
+ };
418
+ if (!u.frozen) return d;
419
+ const x = K.value[u.key] ?? 0;
420
+ return {
421
+ ...d,
422
+ position: 'sticky',
423
+ left: `${x}px`,
424
+ zIndex: a ? 30 : 10,
425
+ background: '#ffffff'
426
+ };
427
+ }
428
+ return (u, a) => (
429
+ b(),
430
+ p('div', _e, [
431
+ n('div', ke, [
432
+ n(
433
+ 'input',
434
+ {
435
+ class: 'flex-1 rounded border border-gray-300 px-3 py-2 text-sm',
436
+ type: 'text',
437
+ value: g(v),
438
+ onInput: I,
439
+ placeholder: 'Search anything...'
440
+ },
441
+ null,
442
+ 40,
443
+ Ce
444
+ ),
445
+ n(
446
+ 'button',
447
+ {
448
+ type: 'button',
449
+ class: 'shifl-grid__pill-button whitespace-nowrap',
450
+ onClick: a[0] || (a[0] = (d) => (D.value = !0))
451
+ },
452
+ ' Edit Columns '
453
+ )
454
+ ]),
455
+ n('div', $e, [
456
+ n('span', null, _(e.config.name ?? 'Shifl Grid'), 1),
457
+ n('span', Se, ' Showing ' + _(F.value.length) + ' of ' + _(r.value.rows.length), 1)
458
+ ]),
459
+ n('div', ze, [
460
+ n('table', Ge, [
461
+ n('thead', null, [
462
+ n('tr', null, [
463
+ (b(!0),
464
+ p(
465
+ $,
466
+ null,
467
+ S(g(l), (d) => {
468
+ var x;
469
+ return (
470
+ b(),
471
+ p(
472
+ 'th',
473
+ {
474
+ key: d.key,
475
+ style: R(E(d, !0)),
476
+ onClick: () => W(d.key)
477
+ },
478
+ [
479
+ n('span', null, _(d.label), 1),
480
+ ((x = g(t)) == null ? void 0 : x.key) === d.key
481
+ ? (b(), p('span', Fe, _(g(t).order === 'asc' ? '▲' : '▼'), 1))
482
+ : M('', !0)
483
+ ],
484
+ 12,
485
+ De
486
+ )
487
+ );
488
+ }),
489
+ 128
490
+ ))
491
+ ])
492
+ ]),
493
+ n('tbody', null, [
494
+ F.value.length
495
+ ? M('', !0)
496
+ : (b(),
497
+ p('tr', Ae, [
498
+ n(
499
+ 'td',
500
+ {
501
+ colspan: g(l).length,
502
+ class: 'text-center text-gray-500 py-6'
503
+ },
504
+ ' No data ',
505
+ 8,
506
+ Me
507
+ )
508
+ ])),
509
+ (b(!0),
510
+ p(
511
+ $,
512
+ null,
513
+ S(
514
+ F.value,
515
+ (d, x) => (
516
+ b(),
517
+ p('tr', { key: x }, [
518
+ (b(!0),
519
+ p(
520
+ $,
521
+ null,
522
+ S(
523
+ g(l),
524
+ (A) => (
525
+ b(),
526
+ p(
527
+ 'td',
528
+ {
529
+ key: A.key,
530
+ style: R(E(A, !1))
531
+ },
532
+ _(J(d[A.key])),
533
+ 5
534
+ )
535
+ )
536
+ ),
537
+ 128
538
+ ))
539
+ ])
540
+ )
541
+ ),
542
+ 128
543
+ ))
544
+ ])
545
+ ])
546
+ ]),
547
+ a[4] ||
548
+ (a[4] = n(
549
+ 'div',
550
+ { class: 'shifl-grid__footer text-xs text-gray-600' },
551
+ ' Row per page 20 ▾ ',
552
+ -1
553
+ )),
554
+ D.value
555
+ ? (b(),
556
+ H(
557
+ we,
558
+ {
559
+ key: 0,
560
+ 'title-prefix': e.config.name,
561
+ columns: g(c),
562
+ onClose: a[1] || (a[1] = (d) => (D.value = !1)),
563
+ onToggle: g(f),
564
+ onToggleFrozen: g(w),
565
+ onMove: g(s),
566
+ onSelectAll: a[2] || (a[2] = (d) => g(h)(!0)),
567
+ onDeselectAll: a[3] || (a[3] = (d) => g(h)(!1)),
568
+ onRestoreDefault: g(o)
569
+ },
570
+ null,
571
+ 8,
572
+ [
573
+ 'title-prefix',
574
+ 'columns',
575
+ 'onToggle',
576
+ 'onToggleFrozen',
577
+ 'onMove',
578
+ 'onRestoreDefault'
579
+ ]
580
+ ))
581
+ : M('', !0)
582
+ ])
583
+ );
584
+ }
585
+ }),
586
+ Ne = {
587
+ install(e) {
588
+ e.component('ShiflGrid', Te);
589
+ }
590
+ };
591
+ function je(e) {
592
+ return {
593
+ rows: e.rows
594
+ };
595
+ }
596
+ function Ve() {
597
+ const e = C(/* @__PURE__ */ new Set());
598
+ function i(r) {
599
+ const c = r.id ?? JSON.stringify(r),
600
+ l = new Set(e.value);
601
+ (l.has(c) ? l.delete(c) : l.add(c), (e.value = l));
602
+ }
603
+ return {
604
+ selectedKeys: e,
605
+ toggleRow: i
606
+ };
607
+ }
608
+ function Re() {
609
+ return {
610
+ // placeholder
611
+ };
612
+ }
613
+ const B = Symbol('shifl-grid-theme'),
614
+ L = {
615
+ surface: 'var(--shifl-surface)',
616
+ surfaceAlt: 'var(--shifl-surface-alt)',
617
+ border: 'var(--shifl-border)',
618
+ text: 'var(--shifl-text)',
619
+ textMuted: 'var(--shifl-text-muted)',
620
+ accent: 'var(--shifl-accent)',
621
+ accentStrong: 'var(--shifl-accent-strong)',
622
+ focus: 'var(--shifl-focus)'
623
+ };
624
+ function Oe(e) {
625
+ const i = C({ ...L, ...e });
626
+ return (Y(B, i), i);
627
+ }
628
+ function Be() {
629
+ const e = q(B);
630
+ return k(() => (e == null ? void 0 : e.value) ?? L);
631
+ }
632
+ const T = {
633
+ sm: 640,
634
+ lg: 1024
635
+ };
636
+ function Le() {
637
+ const e = C(typeof window < 'u' ? window.innerWidth : 0);
638
+ function i() {
639
+ e.value = window.innerWidth;
640
+ }
641
+ return (
642
+ Q(() => {
643
+ window.addEventListener('resize', i);
644
+ }),
645
+ X(() => {
646
+ window.removeEventListener('resize', i);
647
+ }),
648
+ {
649
+ width: e,
650
+ isMobile: k(() => e.value < T.sm),
651
+ isTablet: k(() => e.value >= T.sm && e.value < T.lg)
652
+ }
653
+ );
654
+ }
655
+ function Pe() {
656
+ return {
657
+ // placeholder
658
+ };
659
+ }
660
+ function Ke() {
661
+ return {
662
+ // placeholder
663
+ };
664
+ }
665
+ function We() {
666
+ return {
667
+ // placeholder
668
+ };
669
+ }
670
+ export {
671
+ Te as ShiflGrid,
672
+ Ne as ShiflGridPlugin,
673
+ Oe as provideGridTheme,
674
+ Le as useBreakpoints,
675
+ ee as useGridColumns,
676
+ je as useGridData,
677
+ Re as useGridEditing,
678
+ ne as useGridFilter,
679
+ Pe as useGridInfiniteScroll,
680
+ Ve as useGridSelection,
681
+ te as useGridSort,
682
+ Be as useGridTheme,
683
+ We as useGridTour,
684
+ Ke as useVirtualScroll
685
+ };