@nexxtmove/ui 1.26.0 → 1.27.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/dist/components/molecules/Tree/Tree.vue.d.ts +31 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +281 -103
- package/dist/nuxt.js +1 -0
- package/package.json +1 -1
- package/src/components/molecules/Tree/Tree.vue +342 -0
- package/src/components.json +1 -0
- package/src/index.ts +2 -0
- package/tailwind/nexxtmove.tailwind.custom.css +6 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { NexxtIconName } from '../../atoms/Icon/Icon.vue';
|
|
2
|
+
export interface NexxtTreeNode {
|
|
3
|
+
/** Unique within the tree; this is what `selected` and `collapsed` hold. */
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
icon?: NexxtIconName;
|
|
7
|
+
/** A node with children gets a chevron and can be folded. */
|
|
8
|
+
children?: NexxtTreeNode[];
|
|
9
|
+
}
|
|
10
|
+
export interface NexxtTreeProps {
|
|
11
|
+
/** The top-level nodes; nest `children` for deeper levels. */
|
|
12
|
+
nodes: NexxtTreeNode[];
|
|
13
|
+
/** Accessible name for the tree, e.g. the heading above it. */
|
|
14
|
+
label: string;
|
|
15
|
+
}
|
|
16
|
+
type __VLS_Props = NexxtTreeProps;
|
|
17
|
+
type __VLS_ModelProps = {
|
|
18
|
+
'selected'?: string | null;
|
|
19
|
+
/** Ids of the nodes whose children are hidden. Tracking the collapsed ones makes "everything open" the default. */
|
|
20
|
+
'collapsed'?: string[];
|
|
21
|
+
};
|
|
22
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
23
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
24
|
+
"update:selected": (value: string | null) => any;
|
|
25
|
+
"update:collapsed": (value: string[]) => any;
|
|
26
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
27
|
+
"onUpdate:selected"?: ((value: string | null) => any) | undefined;
|
|
28
|
+
"onUpdate:collapsed"?: ((value: string[]) => any) | undefined;
|
|
29
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
30
|
+
declare const _default: typeof __VLS_export;
|
|
31
|
+
export default _default;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type { CustomIconName } from './components/atoms/Icon/customIcons';
|
|
|
7
7
|
export type { NexxtTabItem } from './components/molecules/Tabs/Tabs.vue';
|
|
8
8
|
export type { NexxtPageCardProps, NexxtPageCardSlots, } from './components/molecules/PageCard/PageCard.vue';
|
|
9
9
|
export type { NexxtPageMockupType } from './components/molecules/PageMockup/PageMockup.vue';
|
|
10
|
+
export type { NexxtTreeNode, NexxtTreeProps } from './components/molecules/Tree/Tree.vue';
|
|
10
11
|
export type { EditorAlignItemsMessages, EditorAlignItemsValue, } from './components/editor/molecules/EditorAlignItems/EditorAlignItems.vue';
|
|
11
12
|
export type { EditorFlexDirectionMessages, EditorFlexDirectionValue, } from './components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue';
|
|
12
13
|
export type { EditorGapMessages, EditorGapValue, } from './components/editor/molecules/EditorGap/EditorGap.vue';
|
|
@@ -93,4 +94,5 @@ export { default as NexxtToast } from './components/molecules/Toast/Toast.vue';
|
|
|
93
94
|
export { default as NexxtToaster } from './components/organisms/Toaster/Toaster.vue';
|
|
94
95
|
export { default as NexxtToggleGroup } from './components/molecules/ToggleGroup/ToggleGroup.vue';
|
|
95
96
|
export { default as NexxtTooltip } from './components/atoms/Tooltip/Tooltip.vue';
|
|
97
|
+
export { default as NexxtTree } from './components/molecules/Tree/Tree.vue';
|
|
96
98
|
export { default as NexxtVideoPlayer } from './components/organisms/VideoPlayer/VideoPlayer.vue';
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Fragment as e, Teleport as t, Transition as n, TransitionGroup as r, computed as i, createBlock as a, createCommentVNode as o, createElementBlock as s, createElementVNode as c, createSlots as l, createStaticVNode as u, createTextVNode as d, createVNode as f, defineComponent as p, getCurrentInstance as m, guardReactiveProps as h, mergeModels as g, mergeProps as _, nextTick as v, normalizeClass as y, normalizeProps as b, normalizeStyle as x, onMounted as S, onUnmounted as C, openBlock as w, ref as T, renderList as E, renderSlot as D, resolveDynamicComponent as O, toDisplayString as k, unref as A, useAttrs as j, useCssVars as M, useModel as N, useTemplateRef as P, vModelCheckbox as F, vModelDynamic as I, vModelText as L, watch as R, watchEffect as z, withCtx as B, withDirectives as V, withKeys as H, withModifiers as U } from "vue";
|
|
2
2
|
import ee from "@number-flow/vue";
|
|
3
|
-
import { addMonths as W, eachDayOfInterval as
|
|
4
|
-
import { fromZonedTime as
|
|
5
|
-
import { nl as
|
|
6
|
-
import { ColorAreaArea as
|
|
3
|
+
import { addMonths as W, eachDayOfInterval as te, endOfDay as ne, endOfMonth as G, endOfWeek as re, format as K, getHours as ie, getMinutes as ae, isAfter as oe, isBefore as se, isSameDay as ce, isSameMonth as le, setHours as ue, setMinutes as de, startOfDay as fe, startOfMonth as pe, startOfWeek as me, subMonths as he } from "date-fns";
|
|
4
|
+
import { fromZonedTime as ge, toZonedTime as q } from "date-fns-tz";
|
|
5
|
+
import { nl as _e } from "date-fns/locale";
|
|
6
|
+
import { ColorAreaArea as ve, ColorAreaRoot as ye, ColorAreaThumb as be, ColorFieldInput as J, ColorFieldRoot as Y, ColorSliderRoot as xe, ColorSliderThumb as Se, ColorSliderTrack as Ce, ColorSwatch as we, DialogClose as Te, DialogContent as Ee, DialogDescription as De, DialogOverlay as Oe, DialogPortal as ke, DialogRoot as Ae, DialogTitle as je, PaginationEllipsis as Me, PaginationFirst as Ne, PaginationLast as Pe, PaginationList as Fe, PaginationListItem as Ie, PaginationNext as Le, PaginationPrev as Re, PaginationRoot as ze, SliderRange as Be, SliderRoot as Ve, SliderThumb as He, SliderTrack as Ue, TooltipContent as We, TooltipPortal as Ge, TooltipProvider as Ke, TooltipRoot as qe, TooltipTrigger as Je, colorToString as Ye, normalizeColor as Xe, setChannelValue as Ze } from "reka-ui";
|
|
7
7
|
import { autoUpdate as Qe, flip as $e, offset as et, shift as tt, size as nt, useFloating as rt } from "@floating-ui/vue";
|
|
8
8
|
import { useEventListener as it, useFullscreen as at, useMediaControls as ot, useResizeObserver as st } from "@vueuse/core";
|
|
9
9
|
//#region src/components/molecules/TimelineEvent/TimelineTypes.ts
|
|
@@ -590,9 +590,9 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
590
590
|
],
|
|
591
591
|
setup(e, { emit: t }) {
|
|
592
592
|
let r = e, a = t, l = i(() => {
|
|
593
|
-
let e =
|
|
593
|
+
let e = K(r.viewDate, "MMM", { locale: r.locale }).replace(".", "").trim();
|
|
594
594
|
return e.charAt(0).toUpperCase() + e.slice(1) + ".";
|
|
595
|
-
}), u = i(() =>
|
|
595
|
+
}), u = i(() => K(r.viewDate, "yyyy")), d = {
|
|
596
596
|
enterActiveClass: "transition-all duration-200 ease-out",
|
|
597
597
|
enterFromClass: "translate-y-full",
|
|
598
598
|
leaveActiveClass: "transition-all duration-200 ease-out absolute inset-x-0 top-0",
|
|
@@ -686,14 +686,14 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
686
686
|
emits: ["select"],
|
|
687
687
|
setup(t, { expose: n, emit: r }) {
|
|
688
688
|
let a = t, l = r, u = P("dayButtonsRef"), d = (e) => {
|
|
689
|
-
let t =
|
|
690
|
-
return
|
|
691
|
-
}, f = (e) => a.modelValue ?
|
|
689
|
+
let t = q(e, a.timezone), n = q(/* @__PURE__ */ new Date(), a.timezone);
|
|
690
|
+
return ce(t, n);
|
|
691
|
+
}, f = (e) => a.modelValue ? ce(e, a.modelValue) : !1, p = (e) => a.markedDates.some((t) => ce(t, e)), m = i(() => {
|
|
692
692
|
let e = [];
|
|
693
693
|
for (let t = 0; t < a.calendarDays.length; t += 7) e.push(a.calendarDays.slice(t, t + 7));
|
|
694
694
|
return e;
|
|
695
695
|
}), h = i(() => a.calendarDays.length === 0 ? [] : a.calendarDays.slice(0, 7).map((e) => {
|
|
696
|
-
let t =
|
|
696
|
+
let t = K(e, "EEEEEE", { locale: a.locale });
|
|
697
697
|
return t.charAt(0).toUpperCase() + t.slice(1);
|
|
698
698
|
})), g = (e, t) => {
|
|
699
699
|
let n = t;
|
|
@@ -722,9 +722,9 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
722
722
|
n >= 0 && n < a.calendarDays.length && (e.preventDefault(), u.value?.[n]?.focus());
|
|
723
723
|
};
|
|
724
724
|
return S(() => {
|
|
725
|
-
a.calendarDays.findIndex((e) => a.modelValue &&
|
|
725
|
+
a.calendarDays.findIndex((e) => a.modelValue && ce(e, a.modelValue) || !a.modelValue && d(e));
|
|
726
726
|
}), n({ focus: (e) => {
|
|
727
|
-
let t = a.calendarDays.findIndex((t) =>
|
|
727
|
+
let t = a.calendarDays.findIndex((t) => ce(t, e));
|
|
728
728
|
t !== -1 && u.value?.[t]?.focus();
|
|
729
729
|
} }), (n, r) => (w(), s("div", Nt, [c("div", Pt, [(w(!0), s(e, null, E(h.value, (e) => (w(), s("div", {
|
|
730
730
|
key: e,
|
|
@@ -747,11 +747,11 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
747
747
|
ref: u,
|
|
748
748
|
type: "button",
|
|
749
749
|
disabled: t.isDisabled(e),
|
|
750
|
-
"aria-label": A(
|
|
751
|
-
tabindex: A(
|
|
750
|
+
"aria-label": A(K)(e, "d MMMM yyyy", { locale: t.locale }),
|
|
751
|
+
tabindex: A(le)(e, t.viewDate) ? 0 : -1,
|
|
752
752
|
class: y([
|
|
753
753
|
"relative flex size-8 items-center justify-center rounded-xl text-xs transition-colors duration-150 outline-none focus:ring-2 focus:ring-cornflower-blue-500 focus:ring-offset-1",
|
|
754
|
-
A(
|
|
754
|
+
A(le)(e, t.viewDate) ? "text-gray-900" : "text-gray-300",
|
|
755
755
|
f(e) ? "bg-cornflower-blue-500 font-medium text-white!" : "",
|
|
756
756
|
d(e) && !f(e) ? "font-medium text-cornflower-blue-500! ring-1 ring-cornflower-blue-500" : "",
|
|
757
757
|
d(e) && f(e) ? "ring-2 ring-cornflower-blue-500 ring-offset-2" : "",
|
|
@@ -760,7 +760,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
760
760
|
]),
|
|
761
761
|
onClick: (t) => l("select", e),
|
|
762
762
|
onKeydown: (e) => g(e, r * 7 + n)
|
|
763
|
-
}, [c("span", Rt, k(A(
|
|
763
|
+
}, [c("span", Rt, k(A(K)(e, "d")), 1), p(e) ? (w(), s("span", {
|
|
764
764
|
key: 0,
|
|
765
765
|
class: y(["absolute bottom-1 left-1/2 size-1 -translate-x-1/2 rounded-full", f(e) ? "bg-white" : "bg-cornflower-blue-500"])
|
|
766
766
|
}, null, 2)) : o("", !0)], 42, Lt)], 8, It))), 128))]))), 128))]));
|
|
@@ -786,17 +786,17 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
786
786
|
emits: ["select"],
|
|
787
787
|
setup(t, { emit: n }) {
|
|
788
788
|
let r = t, a = n, o = i(() => Array.from({ length: 12 }, (e, t) => {
|
|
789
|
-
let n =
|
|
789
|
+
let n = q(new Date(Date.UTC(r.viewYear, t, 1)), r.timezone), i = K(n, "LLL", { locale: r.locale }).replace(".", "").trim();
|
|
790
790
|
return {
|
|
791
791
|
index: t,
|
|
792
792
|
label: i.charAt(0).toUpperCase() + i.slice(1)
|
|
793
793
|
};
|
|
794
794
|
})), c = (e) => {
|
|
795
|
-
let t = r.viewYear, n =
|
|
796
|
-
return !!(r.minDate &&
|
|
795
|
+
let t = r.viewYear, n = q(new Date(Date.UTC(t, e, 1)), r.timezone);
|
|
796
|
+
return !!(r.minDate && G(n) < fe(q(r.minDate, r.timezone)) || r.maxDate && pe(n) > ne(q(r.maxDate, r.timezone)));
|
|
797
797
|
}, l = (e) => {
|
|
798
798
|
if (!r.modelValue) return !1;
|
|
799
|
-
let t =
|
|
799
|
+
let t = q(r.modelValue, r.timezone);
|
|
800
800
|
return t.getFullYear() === r.viewYear && t.getMonth() === e;
|
|
801
801
|
}, u = (e) => e === r.currentMonth;
|
|
802
802
|
return (t, n) => (w(), s("div", Bt, [(w(!0), s(e, null, E(o.value, (e) => (w(), s("button", {
|
|
@@ -826,7 +826,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
826
826
|
emits: ["select"],
|
|
827
827
|
setup(t, { emit: n }) {
|
|
828
828
|
let r = t, a = n, o = P("yearScrollerRef"), l = i(() => {
|
|
829
|
-
let e = r.minDate ?
|
|
829
|
+
let e = r.minDate ? q(r.minDate, r.timezone).getFullYear() : r.viewYear - 100, t = r.maxDate ? q(r.maxDate, r.timezone).getFullYear() : r.viewYear + 20;
|
|
830
830
|
return Array.from({ length: t - e + 1 }, (t, n) => e + n);
|
|
831
831
|
}), u = (e) => {
|
|
832
832
|
if (!o.value) return;
|
|
@@ -862,16 +862,16 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
862
862
|
emits: ["update:modelValue"],
|
|
863
863
|
setup(e, { emit: t }) {
|
|
864
864
|
let n = e, r = t, a = i({
|
|
865
|
-
get: () => n.modelValue ?
|
|
865
|
+
get: () => n.modelValue ? ie(n.modelValue) : ie(/* @__PURE__ */ new Date()),
|
|
866
866
|
set: (e) => {
|
|
867
867
|
let t = n.modelValue || /* @__PURE__ */ new Date();
|
|
868
|
-
r("update:modelValue",
|
|
868
|
+
r("update:modelValue", ue(t, Number(e)));
|
|
869
869
|
}
|
|
870
870
|
}), o = i({
|
|
871
|
-
get: () => n.modelValue ?
|
|
871
|
+
get: () => n.modelValue ? ae(n.modelValue) : ae(/* @__PURE__ */ new Date()),
|
|
872
872
|
set: (e) => {
|
|
873
873
|
let t = n.modelValue || /* @__PURE__ */ new Date();
|
|
874
|
-
r("update:modelValue",
|
|
874
|
+
r("update:modelValue", de(t, Number(e)));
|
|
875
875
|
}
|
|
876
876
|
}), l = (e) => e.toString().padStart(2, "0"), u = () => {
|
|
877
877
|
a.value = (a.value + 1) % 24;
|
|
@@ -916,7 +916,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
916
916
|
name: "NexxtCalendar",
|
|
917
917
|
__name: "Calendar",
|
|
918
918
|
props: /*@__PURE__*/ g({
|
|
919
|
-
locale: { default: () =>
|
|
919
|
+
locale: { default: () => _e },
|
|
920
920
|
markedDates: { default: () => [] },
|
|
921
921
|
disabledDates: { default: () => [] },
|
|
922
922
|
minDate: {},
|
|
@@ -936,41 +936,41 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
936
936
|
}),
|
|
937
937
|
emits: /*@__PURE__*/ g(["select"], ["update:modelValue"]),
|
|
938
938
|
setup(e, { emit: t }) {
|
|
939
|
-
let r = N(e, "modelValue"), l = t, u = T(r.value ?
|
|
939
|
+
let r = N(e, "modelValue"), l = t, u = T(r.value ? q(new Date(r.value), e.timezone) : q(/* @__PURE__ */ new Date(), e.timezone)), d = T("days"), p = T(null), m = T("fade");
|
|
940
940
|
R(r, (t) => {
|
|
941
|
-
t && (u.value =
|
|
941
|
+
t && (u.value = q(new Date(t), e.timezone));
|
|
942
942
|
});
|
|
943
943
|
let h = i(() => {
|
|
944
|
-
let e = pe(
|
|
945
|
-
return
|
|
944
|
+
let e = me(pe(u.value), { weekStartsOn: 1 }), t = re(G(u.value), { weekStartsOn: 1 });
|
|
945
|
+
return te({
|
|
946
946
|
start: e,
|
|
947
947
|
end: t
|
|
948
948
|
});
|
|
949
949
|
}), g = (t) => {
|
|
950
|
-
let n =
|
|
951
|
-
return !!(e.disabledDates.some((t) =>
|
|
950
|
+
let n = q(t, e.timezone);
|
|
951
|
+
return !!(e.disabledDates.some((t) => ce(q(t, e.timezone), n)) || e.minDate && se(n, fe(q(e.minDate, e.timezone))) || e.maxDate && oe(n, ne(q(e.maxDate, e.timezone))));
|
|
952
952
|
}, v = (t) => {
|
|
953
|
-
let n =
|
|
954
|
-
g(n) || (
|
|
953
|
+
let n = q(t, e.timezone);
|
|
954
|
+
g(n) || (le(n, u.value) || (u.value = pe(n)), r.value = ge(n, e.timezone), l("select", r.value));
|
|
955
955
|
}, b = (t) => {
|
|
956
956
|
m.value = "fade";
|
|
957
|
-
let n =
|
|
957
|
+
let n = q(new Date(Date.UTC(u.value.getUTCFullYear(), t, 1)), e.timezone);
|
|
958
958
|
u.value = n, d.value = "days";
|
|
959
959
|
}, x = (t) => {
|
|
960
|
-
let n =
|
|
960
|
+
let n = q(new Date(Date.UTC(t, u.value.getUTCMonth(), 1)), e.timezone);
|
|
961
961
|
u.value = n, d.value = "months";
|
|
962
962
|
}, S = i(() => {
|
|
963
963
|
if (d.value !== "days") return !1;
|
|
964
964
|
if (!e.minDate) return !0;
|
|
965
|
-
let t =
|
|
966
|
-
return !
|
|
965
|
+
let t = he(u.value, 1);
|
|
966
|
+
return !se(G(t), fe(q(e.minDate, e.timezone)));
|
|
967
967
|
}), C = i(() => {
|
|
968
968
|
if (d.value !== "days") return !1;
|
|
969
969
|
if (!e.maxDate) return !0;
|
|
970
970
|
let t = W(u.value, 1);
|
|
971
|
-
return !
|
|
971
|
+
return !oe(pe(t), ne(q(e.maxDate, e.timezone)));
|
|
972
972
|
}), E = () => {
|
|
973
|
-
S.value && (m.value = "slide-prev", u.value =
|
|
973
|
+
S.value && (m.value = "slide-prev", u.value = he(u.value, 1));
|
|
974
974
|
}, D = () => {
|
|
975
975
|
C.value && (m.value = "slide-next", u.value = W(u.value, 1));
|
|
976
976
|
}, O = () => {
|
|
@@ -1455,7 +1455,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1455
1455
|
}, null, 8, ["class"])
|
|
1456
1456
|
], 10, dn)]),
|
|
1457
1457
|
content: B(() => [c("div", { class: y(["flex flex-col gap-4 rounded-xl bg-white p-4 ring ring-gray-200", e.matchWidth ? "w-full" : "w-70"]) }, [
|
|
1458
|
-
f(A(
|
|
1458
|
+
f(A(ye), {
|
|
1459
1459
|
"model-value": u.value,
|
|
1460
1460
|
"color-space": "hsl",
|
|
1461
1461
|
"x-channel": "saturation",
|
|
@@ -1463,11 +1463,11 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1463
1463
|
class: "relative",
|
|
1464
1464
|
"onUpdate:color": C
|
|
1465
1465
|
}, {
|
|
1466
|
-
default: B(({ style: e }) => [c("div", fn, [f(A(
|
|
1466
|
+
default: B(({ style: e }) => [c("div", fn, [f(A(ve), {
|
|
1467
1467
|
class: "relative h-40 w-full cursor-crosshair outline-none",
|
|
1468
1468
|
style: x(e)
|
|
1469
1469
|
}, {
|
|
1470
|
-
default: B(() => [f(A(
|
|
1470
|
+
default: B(() => [f(A(be), { class: "block size-4 cursor-grab rounded-full border-2 border-white shadow-sm focus:outline-none active:cursor-grabbing" })]),
|
|
1471
1471
|
_: 1
|
|
1472
1472
|
}, 8, ["style"])])]),
|
|
1473
1473
|
_: 1
|
|
@@ -1516,55 +1516,55 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1516
1516
|
name: "chevron-down",
|
|
1517
1517
|
class: "text-[12px]",
|
|
1518
1518
|
"aria-hidden": "true"
|
|
1519
|
-
})])])) : o("", !0)]), _.value === "hex" ? (w(), a(A(
|
|
1519
|
+
})])])) : o("", !0)]), _.value === "hex" ? (w(), a(A(Y), {
|
|
1520
1520
|
key: 0,
|
|
1521
1521
|
"model-value": g.value,
|
|
1522
1522
|
class: "w-full",
|
|
1523
1523
|
"onUpdate:color": C
|
|
1524
1524
|
}, {
|
|
1525
|
-
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", p.value ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(
|
|
1525
|
+
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", p.value ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(J), {
|
|
1526
1526
|
class: "w-full bg-transparent small-normal-mono text-gray-900 placeholder-gray-400 focus:outline-none",
|
|
1527
1527
|
placeholder: "#000000",
|
|
1528
1528
|
onInput: E
|
|
1529
1529
|
})], 2), p.value ? (w(), s("p", vn, k(p.value), 1)) : o("", !0)]),
|
|
1530
1530
|
_: 1
|
|
1531
1531
|
}, 8, ["model-value"])) : _.value === "hsl" ? (w(), s("div", yn, [
|
|
1532
|
-
f(A(
|
|
1532
|
+
f(A(Y), {
|
|
1533
1533
|
"model-value": u.value,
|
|
1534
1534
|
channel: "hue",
|
|
1535
1535
|
"color-space": "hsl",
|
|
1536
1536
|
class: "flex-1",
|
|
1537
1537
|
"onUpdate:color": C
|
|
1538
1538
|
}, {
|
|
1539
|
-
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.hue ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(
|
|
1539
|
+
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.hue ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(J), {
|
|
1540
1540
|
class: "w-full bg-transparent small-normal-mono text-gray-900 placeholder-gray-400 focus:outline-none",
|
|
1541
1541
|
placeholder: "H",
|
|
1542
1542
|
onInput: i[2] ||= (e) => D(e, "hue")
|
|
1543
1543
|
})], 2)]),
|
|
1544
1544
|
_: 1
|
|
1545
1545
|
}, 8, ["model-value"]),
|
|
1546
|
-
f(A(
|
|
1546
|
+
f(A(Y), {
|
|
1547
1547
|
"model-value": u.value,
|
|
1548
1548
|
channel: "saturation",
|
|
1549
1549
|
"color-space": "hsl",
|
|
1550
1550
|
class: "flex-1",
|
|
1551
1551
|
"onUpdate:color": C
|
|
1552
1552
|
}, {
|
|
1553
|
-
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.saturation ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(
|
|
1553
|
+
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.saturation ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(J), {
|
|
1554
1554
|
class: "w-full bg-transparent small-normal-mono text-gray-900 placeholder-gray-400 focus:outline-none",
|
|
1555
1555
|
placeholder: "S",
|
|
1556
1556
|
onInput: i[3] ||= (e) => D(e, "saturation")
|
|
1557
1557
|
})], 2)]),
|
|
1558
1558
|
_: 1
|
|
1559
1559
|
}, 8, ["model-value"]),
|
|
1560
|
-
f(A(
|
|
1560
|
+
f(A(Y), {
|
|
1561
1561
|
"model-value": u.value,
|
|
1562
1562
|
channel: "lightness",
|
|
1563
1563
|
"color-space": "hsl",
|
|
1564
1564
|
class: "flex-1",
|
|
1565
1565
|
"onUpdate:color": C
|
|
1566
1566
|
}, {
|
|
1567
|
-
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.lightness ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(
|
|
1567
|
+
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.lightness ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(J), {
|
|
1568
1568
|
class: "w-full bg-transparent small-normal-mono text-gray-900 placeholder-gray-400 focus:outline-none",
|
|
1569
1569
|
placeholder: "L",
|
|
1570
1570
|
onInput: i[4] ||= (e) => D(e, "lightness")
|
|
@@ -1572,42 +1572,42 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1572
1572
|
_: 1
|
|
1573
1573
|
}, 8, ["model-value"])
|
|
1574
1574
|
])) : _.value === "rgb" ? (w(), s("div", bn, [
|
|
1575
|
-
f(A(
|
|
1575
|
+
f(A(Y), {
|
|
1576
1576
|
"model-value": u.value,
|
|
1577
1577
|
channel: "red",
|
|
1578
1578
|
"color-space": "rgb",
|
|
1579
1579
|
class: "flex-1",
|
|
1580
1580
|
"onUpdate:color": C
|
|
1581
1581
|
}, {
|
|
1582
|
-
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.red ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(
|
|
1582
|
+
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.red ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(J), {
|
|
1583
1583
|
class: "w-full bg-transparent small-normal-mono text-gray-900 placeholder-gray-400 focus:outline-none",
|
|
1584
1584
|
placeholder: "R",
|
|
1585
1585
|
onInput: i[5] ||= (e) => D(e, "red")
|
|
1586
1586
|
})], 2)]),
|
|
1587
1587
|
_: 1
|
|
1588
1588
|
}, 8, ["model-value"]),
|
|
1589
|
-
f(A(
|
|
1589
|
+
f(A(Y), {
|
|
1590
1590
|
"model-value": u.value,
|
|
1591
1591
|
channel: "green",
|
|
1592
1592
|
"color-space": "rgb",
|
|
1593
1593
|
class: "flex-1",
|
|
1594
1594
|
"onUpdate:color": C
|
|
1595
1595
|
}, {
|
|
1596
|
-
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.green ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(
|
|
1596
|
+
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.green ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(J), {
|
|
1597
1597
|
class: "w-full bg-transparent small-normal-mono text-gray-900 placeholder-gray-400 focus:outline-none",
|
|
1598
1598
|
placeholder: "G",
|
|
1599
1599
|
onInput: i[6] ||= (e) => D(e, "green")
|
|
1600
1600
|
})], 2)]),
|
|
1601
1601
|
_: 1
|
|
1602
1602
|
}, 8, ["model-value"]),
|
|
1603
|
-
f(A(
|
|
1603
|
+
f(A(Y), {
|
|
1604
1604
|
"model-value": u.value,
|
|
1605
1605
|
channel: "blue",
|
|
1606
1606
|
"color-space": "rgb",
|
|
1607
1607
|
class: "flex-1",
|
|
1608
1608
|
"onUpdate:color": C
|
|
1609
1609
|
}, {
|
|
1610
|
-
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.blue ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(
|
|
1610
|
+
default: B(() => [c("div", { class: y(["flex h-10 items-center overflow-hidden rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500", h.value.blue ? "ring-brick-400" : "ring-gray-200"]) }, [f(A(J), {
|
|
1611
1611
|
class: "w-full bg-transparent small-normal-mono text-gray-900 placeholder-gray-400 focus:outline-none",
|
|
1612
1612
|
placeholder: "B",
|
|
1613
1613
|
onInput: i[7] ||= (e) => D(e, "blue")
|
|
@@ -1796,21 +1796,21 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1796
1796
|
return !R.value.some((t) => t.label.toLowerCase() === e);
|
|
1797
1797
|
}), ee = i(() => z.value.length > 0 || V.value), W = (e) => {
|
|
1798
1798
|
v.value = [...v.value, L(e)], D.value = "";
|
|
1799
|
-
},
|
|
1799
|
+
}, te = (e) => {
|
|
1800
1800
|
let t = L(e);
|
|
1801
1801
|
v.value = v.value[0] === t ? [] : [t], D.value = "", _("select");
|
|
1802
|
-
},
|
|
1802
|
+
}, ne = () => {
|
|
1803
1803
|
if (p.singleSelect) {
|
|
1804
|
-
z.value.length > 0 ?
|
|
1804
|
+
z.value.length > 0 ? te(z.value[0]) : p.allowNew && G();
|
|
1805
1805
|
return;
|
|
1806
1806
|
}
|
|
1807
|
-
z.value.length === 1 ? W(z.value[0]) : p.allowNew &&
|
|
1808
|
-
},
|
|
1807
|
+
z.value.length === 1 ? W(z.value[0]) : p.allowNew && G();
|
|
1808
|
+
}, G = () => {
|
|
1809
1809
|
let e = D.value.trim();
|
|
1810
1810
|
if (!e) return;
|
|
1811
1811
|
let t = e.toLowerCase(), n = R.value.some((e) => e.label.toLowerCase() === t), r = p.options.some((e) => I(e).toLowerCase() === t);
|
|
1812
1812
|
n || r || (p.singleSelect ? (v.value = [e], D.value = "", _("select")) : (v.value = [...v.value, e], D.value = ""));
|
|
1813
|
-
},
|
|
1813
|
+
}, re = (e) => {
|
|
1814
1814
|
v.value = v.value.filter((t) => t !== e);
|
|
1815
1815
|
};
|
|
1816
1816
|
return l({ focus: () => {
|
|
@@ -1830,7 +1830,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1830
1830
|
placeholder: A(h),
|
|
1831
1831
|
"aria-label": A(h),
|
|
1832
1832
|
onFocus: l[1] ||= (e) => O.value = !0,
|
|
1833
|
-
onKeydown: H(
|
|
1833
|
+
onKeydown: H(ne, ["enter"])
|
|
1834
1834
|
}, null, 8, [
|
|
1835
1835
|
"modelValue",
|
|
1836
1836
|
"left-icon",
|
|
@@ -1859,7 +1859,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1859
1859
|
key: e.value,
|
|
1860
1860
|
class: "origin-left cursor-pointer",
|
|
1861
1861
|
"aria-label": `Verwijder ${e.label}`,
|
|
1862
|
-
onClick: (t) =>
|
|
1862
|
+
onClick: (t) => re(e.value)
|
|
1863
1863
|
}, [f(sn, {
|
|
1864
1864
|
ghost: !0,
|
|
1865
1865
|
class: "group",
|
|
@@ -1893,7 +1893,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1893
1893
|
role: "option",
|
|
1894
1894
|
"aria-selected": v.value.includes(L(e)),
|
|
1895
1895
|
class: y(["flex w-full cursor-pointer items-center gap-2 px-6 py-3 text-left text-sm whitespace-nowrap text-gray-700 transition-colors duration-200 hover:bg-gray-100 hover:text-purple-600 focus:bg-gray-100 focus:outline-none", { "font-medium text-cornflower-blue-600": t.singleSelect && v.value.includes(L(e)) }]),
|
|
1896
|
-
onClick: (n) => t.singleSelect ?
|
|
1896
|
+
onClick: (n) => t.singleSelect ? te(e) : W(e)
|
|
1897
1897
|
}, [d(k(I(e)) + " ", 1), t.singleSelect && v.value.includes(L(e)) ? (w(), a(Z, {
|
|
1898
1898
|
key: 0,
|
|
1899
1899
|
name: "check",
|
|
@@ -1901,7 +1901,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1901
1901
|
})) : o("", !0)], 10, Pn))), 128))]), V.value ? (w(), s("div", {
|
|
1902
1902
|
key: 0,
|
|
1903
1903
|
class: "flex grow-0 items-center gap-4 border-t border-gray-100 px-6 py-3 whitespace-normal text-gray-700",
|
|
1904
|
-
onClick: l[2] ||= (e) =>
|
|
1904
|
+
onClick: l[2] ||= (e) => G()
|
|
1905
1905
|
}, [f(Z, {
|
|
1906
1906
|
name: "plus",
|
|
1907
1907
|
class: "cursor-pointer small-normal",
|
|
@@ -1921,7 +1921,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1921
1921
|
class: "w-full",
|
|
1922
1922
|
"left-icon": A(m),
|
|
1923
1923
|
placeholder: A(h),
|
|
1924
|
-
onKeydown: H(
|
|
1924
|
+
onKeydown: H(ne, ["enter"])
|
|
1925
1925
|
}, null, 8, [
|
|
1926
1926
|
"modelValue",
|
|
1927
1927
|
"left-icon",
|
|
@@ -1950,7 +1950,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1950
1950
|
key: e.value,
|
|
1951
1951
|
class: "origin-left cursor-pointer",
|
|
1952
1952
|
"aria-label": `Verwijder ${e.label}`,
|
|
1953
|
-
onClick: (t) =>
|
|
1953
|
+
onClick: (t) => re(e.value)
|
|
1954
1954
|
}, [f(sn, {
|
|
1955
1955
|
ghost: !0,
|
|
1956
1956
|
class: "group",
|
|
@@ -1973,7 +1973,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1973
1973
|
role: "option",
|
|
1974
1974
|
"aria-selected": v.value.includes(L(e)),
|
|
1975
1975
|
class: y(["flex w-full min-w-42 cursor-pointer items-center gap-2 px-6 py-3 text-left text-sm whitespace-nowrap text-gray-700 transition-colors duration-200 hover:bg-gray-100 hover:text-purple-600 focus:bg-gray-100 focus:outline-none", { "font-medium text-cornflower-blue-600": t.singleSelect && v.value.includes(L(e)) }]),
|
|
1976
|
-
onClick: (n) => t.singleSelect ?
|
|
1976
|
+
onClick: (n) => t.singleSelect ? te(e) : W(e)
|
|
1977
1977
|
}, [d(k(I(e)) + " ", 1), t.singleSelect && v.value.includes(L(e)) ? (w(), a(Z, {
|
|
1978
1978
|
key: 0,
|
|
1979
1979
|
name: "check",
|
|
@@ -1982,7 +1982,7 @@ var pt = { funda: { render: ft } }, Z = /* @__PURE__ */ p({
|
|
|
1982
1982
|
V.value ? (w(), s("div", {
|
|
1983
1983
|
key: 0,
|
|
1984
1984
|
class: "flex grow-0 items-center gap-4 border-t border-gray-100 px-6 py-3 whitespace-normal text-gray-700",
|
|
1985
|
-
onClick: l[5] ||= (e) =>
|
|
1985
|
+
onClick: l[5] ||= (e) => G()
|
|
1986
1986
|
}, [f(Z, {
|
|
1987
1987
|
name: "plus",
|
|
1988
1988
|
class: "cursor-pointer small-normal",
|
|
@@ -6981,26 +6981,204 @@ var Ks = { render: Gs }, qs = { class: "flex items-center justify-end self-stret
|
|
|
6981
6981
|
"leave-to-class"
|
|
6982
6982
|
])], 2)]));
|
|
6983
6983
|
}
|
|
6984
|
-
}), Tl = [
|
|
6984
|
+
}), Tl = ["aria-label"], El = [
|
|
6985
|
+
"aria-level",
|
|
6986
|
+
"aria-posinset",
|
|
6987
|
+
"aria-setsize",
|
|
6988
|
+
"aria-selected",
|
|
6989
|
+
"aria-expanded",
|
|
6990
|
+
"tabindex",
|
|
6991
|
+
"data-tree-id",
|
|
6992
|
+
"onClick",
|
|
6993
|
+
"onFocus"
|
|
6994
|
+
], Dl = ["onClick"], Ol = {
|
|
6995
|
+
key: 1,
|
|
6996
|
+
class: "size-5 shrink-0"
|
|
6997
|
+
}, kl = { class: "truncate" }, Al = 22, jl = "transform 200ms var(--ease-in-out-strong), opacity 80ms linear 120ms", Ml = /* @__PURE__ */ p({
|
|
6998
|
+
name: "NexxtTree",
|
|
6999
|
+
__name: "Tree",
|
|
7000
|
+
props: /*@__PURE__*/ g({
|
|
7001
|
+
nodes: {},
|
|
7002
|
+
label: {}
|
|
7003
|
+
}, {
|
|
7004
|
+
selected: { default: null },
|
|
7005
|
+
selectedModifiers: {},
|
|
7006
|
+
collapsed: { default: () => [] },
|
|
7007
|
+
collapsedModifiers: {}
|
|
7008
|
+
}),
|
|
7009
|
+
emits: ["update:selected", "update:collapsed"],
|
|
7010
|
+
setup(t) {
|
|
7011
|
+
let n = t, l = N(t, "selected"), u = N(t, "collapsed"), d = P("root"), p = T(null), m = i(() => {
|
|
7012
|
+
let e = [], t = (n, r, i) => {
|
|
7013
|
+
n.forEach((a, o) => {
|
|
7014
|
+
let s = !!a.children?.length, c = s && !u.value.includes(a.id);
|
|
7015
|
+
e.push({
|
|
7016
|
+
node: a,
|
|
7017
|
+
depth: r,
|
|
7018
|
+
parentId: i,
|
|
7019
|
+
expandable: s,
|
|
7020
|
+
expanded: c,
|
|
7021
|
+
position: o + 1,
|
|
7022
|
+
setSize: n.length
|
|
7023
|
+
}), c && t(a.children, r + 1, a.id);
|
|
7024
|
+
});
|
|
7025
|
+
};
|
|
7026
|
+
return t(n.nodes, 0, null), e;
|
|
7027
|
+
}), h = i(() => !!l.value && m.value.some((e) => e.node.id === l.value)), g = T({
|
|
7028
|
+
top: 0,
|
|
7029
|
+
height: 0
|
|
7030
|
+
}), _ = P("highlightElement"), b = {
|
|
7031
|
+
none: "",
|
|
7032
|
+
select: "transition-[transform,opacity] duration-200 ease-out-strong",
|
|
7033
|
+
move: "transition-[transform,opacity] duration-200 ease-in-out-strong"
|
|
7034
|
+
}, C = T("none"), D = (e) => Array.from(d.value?.querySelectorAll("[data-tree-id]") ?? []).find((t) => t.dataset.treeId === e && !t.classList.contains("absolute")), O = async () => {
|
|
7035
|
+
if (await v(), !d.value || !h.value) return;
|
|
7036
|
+
let e = D(l.value);
|
|
7037
|
+
e && (g.value = {
|
|
7038
|
+
top: e.offsetTop,
|
|
7039
|
+
height: e.offsetHeight
|
|
7040
|
+
});
|
|
7041
|
+
}, A = async (e) => {
|
|
7042
|
+
let t = C.value;
|
|
7043
|
+
C.value = "none", await e(), await v(), d.value?.getBoundingClientRect(), C.value = t;
|
|
7044
|
+
};
|
|
7045
|
+
R([l, m], ([e], [t]) => {
|
|
7046
|
+
C.value = e === t ? "move" : "select", O();
|
|
7047
|
+
}), st(d, () => {
|
|
7048
|
+
_.value?.getAnimations().length || A(O);
|
|
7049
|
+
}), S(() => A(async () => {
|
|
7050
|
+
await O(), await document.fonts?.ready, await O();
|
|
7051
|
+
}));
|
|
7052
|
+
let j = (e) => {
|
|
7053
|
+
let t = e;
|
|
7054
|
+
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
7055
|
+
let n = D(m.value.find((e) => e.node.id === t.dataset.treeId)?.parentId), r = n ? t.offsetTop - (n.offsetTop + n.offsetHeight) : 0;
|
|
7056
|
+
t.style.transition = "none", t.style.transform = `translateY(${-r}px)`, t.style.opacity = "0", t.style.pointerEvents = "none", t.getBoundingClientRect(), t.style.transition = jl, t.style.transform = "", t.style.opacity = "";
|
|
7057
|
+
}, M = (e) => {
|
|
7058
|
+
let t = e;
|
|
7059
|
+
t.style.transition = "", t.style.pointerEvents = "";
|
|
7060
|
+
}, F = i(() => {
|
|
7061
|
+
let e = m.value.map((e) => e.node.id);
|
|
7062
|
+
return p.value && e.includes(p.value) ? p.value : l.value && e.includes(l.value) ? l.value : e[0] ?? null;
|
|
7063
|
+
}), I = (e) => {
|
|
7064
|
+
u.value = u.value.includes(e) ? u.value.filter((t) => t !== e) : [...u.value, e];
|
|
7065
|
+
}, L = async (e) => {
|
|
7066
|
+
p.value = e, await v(), Array.from(d.value?.querySelectorAll("[data-tree-id]") ?? []).find((t) => t.dataset.treeId === e)?.focus();
|
|
7067
|
+
}, z = (e) => {
|
|
7068
|
+
let t = m.value.findIndex((e) => e.node.id === F.value), n = m.value[t];
|
|
7069
|
+
if (!n) return;
|
|
7070
|
+
let r = (e) => {
|
|
7071
|
+
e && L(e.node.id);
|
|
7072
|
+
};
|
|
7073
|
+
switch (e.key) {
|
|
7074
|
+
case "ArrowDown":
|
|
7075
|
+
r(m.value[t + 1]);
|
|
7076
|
+
break;
|
|
7077
|
+
case "ArrowUp":
|
|
7078
|
+
r(m.value[t - 1]);
|
|
7079
|
+
break;
|
|
7080
|
+
case "Home":
|
|
7081
|
+
r(m.value[0]);
|
|
7082
|
+
break;
|
|
7083
|
+
case "End":
|
|
7084
|
+
r(m.value[m.value.length - 1]);
|
|
7085
|
+
break;
|
|
7086
|
+
case "ArrowRight":
|
|
7087
|
+
n.expandable && !n.expanded ? I(n.node.id) : n.expanded && r(m.value[t + 1]);
|
|
7088
|
+
break;
|
|
7089
|
+
case "ArrowLeft":
|
|
7090
|
+
n.expanded ? I(n.node.id) : n.parentId && L(n.parentId);
|
|
7091
|
+
break;
|
|
7092
|
+
case "Enter":
|
|
7093
|
+
case " ":
|
|
7094
|
+
l.value = n.node.id;
|
|
7095
|
+
break;
|
|
7096
|
+
default: return;
|
|
7097
|
+
}
|
|
7098
|
+
e.preventDefault();
|
|
7099
|
+
};
|
|
7100
|
+
return (n, i) => (w(), s("div", {
|
|
7101
|
+
ref_key: "root",
|
|
7102
|
+
ref: d,
|
|
7103
|
+
role: "tree",
|
|
7104
|
+
"aria-label": t.label,
|
|
7105
|
+
class: "relative isolate",
|
|
7106
|
+
onKeydown: z
|
|
7107
|
+
}, [c("div", {
|
|
7108
|
+
ref_key: "highlightElement",
|
|
7109
|
+
ref: _,
|
|
7110
|
+
"aria-hidden": "true",
|
|
7111
|
+
class: y(["pointer-events-none absolute top-0 left-0 -z-10 w-full rounded-md bg-cornflower-blue-50 motion-reduce:transition-none", [b[C.value], h.value ? "opacity-100" : "opacity-0"]]),
|
|
7112
|
+
style: x({
|
|
7113
|
+
transform: `translateY(${g.value.top}px)`,
|
|
7114
|
+
height: `${g.value.height}px`
|
|
7115
|
+
}),
|
|
7116
|
+
"data-tree-highlight": ""
|
|
7117
|
+
}, null, 6), f(r, {
|
|
7118
|
+
tag: "div",
|
|
7119
|
+
role: "group",
|
|
7120
|
+
"leave-active-class": "invisible absolute w-full transition-none!",
|
|
7121
|
+
"move-class": "transition-transform duration-200 ease-in-out-strong motion-reduce:transition-none",
|
|
7122
|
+
onEnter: j,
|
|
7123
|
+
onAfterEnter: M,
|
|
7124
|
+
onEnterCancelled: M
|
|
7125
|
+
}, {
|
|
7126
|
+
default: B(() => [(w(!0), s(e, null, E(m.value, (e) => (w(), s("div", {
|
|
7127
|
+
key: e.node.id,
|
|
7128
|
+
role: "treeitem",
|
|
7129
|
+
"aria-level": e.depth + 1,
|
|
7130
|
+
"aria-posinset": e.position,
|
|
7131
|
+
"aria-setsize": e.setSize,
|
|
7132
|
+
"aria-selected": l.value === e.node.id,
|
|
7133
|
+
"aria-expanded": e.expandable ? e.expanded : void 0,
|
|
7134
|
+
tabindex: e.node.id === F.value ? 0 : -1,
|
|
7135
|
+
"data-tree-id": e.node.id,
|
|
7136
|
+
class: y(["group mb-0.5 flex cursor-pointer items-center gap-1.5 rounded-md py-1 pr-2 small-normal transition-colors duration-150 select-none focus-visible:outline-2 focus-visible:outline-cornflower-blue-500 motion-reduce:transition-none", l.value === e.node.id ? "text-cornflower-blue-600" : "text-gray-800 hover:bg-gray-100"]),
|
|
7137
|
+
style: x({ paddingLeft: `${e.depth * Al + 4}px` }),
|
|
7138
|
+
onClick: (t) => l.value = e.node.id,
|
|
7139
|
+
onFocus: (t) => p.value = e.node.id
|
|
7140
|
+
}, [
|
|
7141
|
+
e.expandable ? (w(), s("button", {
|
|
7142
|
+
key: 0,
|
|
7143
|
+
type: "button",
|
|
7144
|
+
tabindex: "-1",
|
|
7145
|
+
"aria-hidden": "true",
|
|
7146
|
+
class: "flex size-5 shrink-0 cursor-pointer items-center justify-center text-gray-400 transition-colors duration-150 group-hover:text-gray-600 hover:text-gray-600 motion-reduce:transition-none",
|
|
7147
|
+
onClick: U((t) => I(e.node.id), ["stop"])
|
|
7148
|
+
}, [f(Z, {
|
|
7149
|
+
name: "chevron-down",
|
|
7150
|
+
class: y(["extra-small-normal transition-transform duration-150 ease-out motion-reduce:transition-none", !e.expanded && "-rotate-90"])
|
|
7151
|
+
}, null, 8, ["class"])], 8, Dl)) : (w(), s("span", Ol)),
|
|
7152
|
+
e.node.icon ? (w(), a(Z, {
|
|
7153
|
+
key: 2,
|
|
7154
|
+
name: e.node.icon,
|
|
7155
|
+
class: y(["shrink-0 transition-colors duration-150 motion-reduce:transition-none", l.value === e.node.id ? "text-cornflower-blue-600" : "text-gray-600"])
|
|
7156
|
+
}, null, 8, ["name", "class"])) : o("", !0),
|
|
7157
|
+
c("span", kl, k(e.node.label), 1)
|
|
7158
|
+
], 46, El))), 128))]),
|
|
7159
|
+
_: 1
|
|
7160
|
+
})], 40, Tl));
|
|
7161
|
+
}
|
|
7162
|
+
}), Nl = [
|
|
6985
7163
|
"src",
|
|
6986
7164
|
"loop",
|
|
6987
7165
|
"aria-label"
|
|
6988
|
-
],
|
|
7166
|
+
], Pl = {
|
|
6989
7167
|
key: 0,
|
|
6990
7168
|
role: "alert",
|
|
6991
7169
|
class: "absolute inset-0 flex flex-col items-center justify-center gap-3 rounded-lg bg-gray-900 text-white"
|
|
6992
|
-
},
|
|
7170
|
+
}, Fl = { class: "heading-4" }, Il = { class: "max-w-xs truncate extra-small-normal text-white/50" }, Ll = {
|
|
6993
7171
|
key: 0,
|
|
6994
7172
|
class: "pointer-events-none absolute inset-0 flex items-center justify-center"
|
|
6995
|
-
},
|
|
7173
|
+
}, Rl = {
|
|
6996
7174
|
class: "flex size-16 items-center justify-center rounded-full bg-black/50 text-white",
|
|
6997
7175
|
"aria-hidden": "true"
|
|
6998
|
-
},
|
|
7176
|
+
}, zl = [
|
|
6999
7177
|
"aria-label",
|
|
7000
7178
|
"aria-valuemax",
|
|
7001
7179
|
"aria-valuenow",
|
|
7002
7180
|
"aria-valuetext"
|
|
7003
|
-
],
|
|
7181
|
+
], Bl = { class: "flex items-center gap-2" }, Vl = ["aria-label"], Hl = { class: "extra-small-normal text-white/70 tabular-nums" }, Ul = ["aria-label"], Wl = ["aria-label"], Gl = /* @__PURE__ */ p({
|
|
7004
7182
|
__name: "VideoPlayer",
|
|
7005
7183
|
props: {
|
|
7006
7184
|
src: {},
|
|
@@ -7041,27 +7219,27 @@ var Ks = { render: Gs }, qs = { class: "flex items-center justify-end self-stret
|
|
|
7041
7219
|
R(g, (e) => {
|
|
7042
7220
|
!e && H && (H = !1, V.value = null);
|
|
7043
7221
|
});
|
|
7044
|
-
let
|
|
7222
|
+
let te = (e) => {
|
|
7045
7223
|
if (!z.value) return 0;
|
|
7046
7224
|
let t = z.value.getBoundingClientRect(), n = "touches" in e ? e.touches[0]?.clientX ?? 0 : e.clientX;
|
|
7047
7225
|
return Math.max(0, Math.min(1, (n - t.left) / t.width));
|
|
7048
|
-
},
|
|
7049
|
-
V.value =
|
|
7050
|
-
},
|
|
7226
|
+
}, ne = (e) => {
|
|
7227
|
+
V.value = te(e);
|
|
7228
|
+
}, G = (e) => {
|
|
7051
7229
|
if (!m.value) return;
|
|
7052
7230
|
let t = Math.max(0, Math.min(m.value, p.value + e));
|
|
7053
7231
|
H = !0, p.value = t;
|
|
7054
|
-
},
|
|
7055
|
-
e.key === "ArrowLeft" ? (e.preventDefault(),
|
|
7056
|
-
},
|
|
7232
|
+
}, re = (e) => {
|
|
7233
|
+
e.key === "ArrowLeft" ? (e.preventDefault(), G(-5)) : e.key === "ArrowRight" ? (e.preventDefault(), G(5)) : e.key === "Home" ? (e.preventDefault(), G(-Infinity)) : e.key === "End" && (e.preventDefault(), G(Infinity));
|
|
7234
|
+
}, K = () => {
|
|
7057
7235
|
V.value !== null && m.value ? (H = !0, p.value = V.value * m.value) : V.value = null;
|
|
7058
7236
|
};
|
|
7059
7237
|
return it(document, "mousemove", (e) => {
|
|
7060
|
-
V.value !== null && (V.value =
|
|
7238
|
+
V.value !== null && (V.value = te(e));
|
|
7061
7239
|
}), it(document, "mouseup", () => {
|
|
7062
|
-
V.value !== null &&
|
|
7240
|
+
V.value !== null && K();
|
|
7063
7241
|
}), it(document, "touchend", () => {
|
|
7064
|
-
V.value !== null &&
|
|
7242
|
+
V.value !== null && K();
|
|
7065
7243
|
}), S(() => {
|
|
7066
7244
|
r.autoplay && (u.value = !0), r.muted && (h.value = !0);
|
|
7067
7245
|
}), t({
|
|
@@ -7081,15 +7259,15 @@ var Ks = { render: Gs }, qs = { class: "flex items-center justify-end self-stret
|
|
|
7081
7259
|
"aria-label": a.value.video,
|
|
7082
7260
|
onError: r[0] ||= (e) => E.value = !0,
|
|
7083
7261
|
onClick: r[1] ||= (t) => e.showControls === !1 ? void 0 : I()
|
|
7084
|
-
}, null, 42,
|
|
7085
|
-
E.value ? (w(), s("div",
|
|
7262
|
+
}, null, 42, Nl),
|
|
7263
|
+
E.value ? (w(), s("div", Pl, [
|
|
7086
7264
|
f(Z, {
|
|
7087
7265
|
name: "circle-exclamation",
|
|
7088
7266
|
class: "text-3xl text-red-400",
|
|
7089
7267
|
"aria-hidden": "true"
|
|
7090
7268
|
}),
|
|
7091
|
-
c("p",
|
|
7092
|
-
c("p",
|
|
7269
|
+
c("p", Fl, k(a.value.error), 1),
|
|
7270
|
+
c("p", Il, k(e.src), 1)
|
|
7093
7271
|
])) : o("", !0),
|
|
7094
7272
|
f(n, {
|
|
7095
7273
|
"enter-active-class": "transition-opacity duration-100 ease-out",
|
|
@@ -7097,7 +7275,7 @@ var Ks = { render: Gs }, qs = { class: "flex items-center justify-end self-stret
|
|
|
7097
7275
|
"enter-from-class": "opacity-0",
|
|
7098
7276
|
"leave-to-class": "opacity-0"
|
|
7099
7277
|
}, {
|
|
7100
|
-
default: B(() => [e.showControls !== !1 && D.value && !E.value ? (w(), s("div",
|
|
7278
|
+
default: B(() => [e.showControls !== !1 && D.value && !E.value ? (w(), s("div", Ll, [c("div", Rl, [f(Z, {
|
|
7101
7279
|
name: D.value,
|
|
7102
7280
|
class: "text-2xl"
|
|
7103
7281
|
}, null, 8, ["name"])])])) : o("", !0)]),
|
|
@@ -7118,14 +7296,14 @@ var Ks = { render: Gs }, qs = { class: "flex items-center justify-end self-stret
|
|
|
7118
7296
|
"aria-valuetext": F(W.value),
|
|
7119
7297
|
tabindex: "0",
|
|
7120
7298
|
class: "relative h-1.5 cursor-pointer rounded-full bg-white/20",
|
|
7121
|
-
onMousedown:
|
|
7122
|
-
onTouchstart: U(
|
|
7123
|
-
onKeydown:
|
|
7299
|
+
onMousedown: ne,
|
|
7300
|
+
onTouchstart: U(ne, ["prevent"]),
|
|
7301
|
+
onKeydown: re,
|
|
7124
7302
|
onTouchmove: r[2] ||= U((e) => {
|
|
7125
|
-
V.value !== null && (V.value =
|
|
7303
|
+
V.value !== null && (V.value = te(e));
|
|
7126
7304
|
}, ["prevent"]),
|
|
7127
7305
|
onTouchend: r[3] ||= () => {
|
|
7128
|
-
V.value !== null &&
|
|
7306
|
+
V.value !== null && K();
|
|
7129
7307
|
}
|
|
7130
7308
|
}, [
|
|
7131
7309
|
c("div", {
|
|
@@ -7140,7 +7318,7 @@ var Ks = { render: Gs }, qs = { class: "flex items-center justify-end self-stret
|
|
|
7140
7318
|
class: "absolute top-1/2 size-3 -translate-1/2 rounded-full bg-sapphire-100 opacity-0 shadow-sm transition-opacity group-hover/player:opacity-100",
|
|
7141
7319
|
style: x({ left: `${ee.value}%` })
|
|
7142
7320
|
}, null, 4)
|
|
7143
|
-
], 40,
|
|
7321
|
+
], 40, zl), c("div", Bl, [
|
|
7144
7322
|
c("button", {
|
|
7145
7323
|
type: "button",
|
|
7146
7324
|
"aria-label": A(u) ? a.value.pause : a.value.play,
|
|
@@ -7150,8 +7328,8 @@ var Ks = { render: Gs }, qs = { class: "flex items-center justify-end self-stret
|
|
|
7150
7328
|
name: A(u) ? "pause" : "play",
|
|
7151
7329
|
class: "text-sm",
|
|
7152
7330
|
"aria-hidden": "true"
|
|
7153
|
-
}, null, 8, ["name"])], 8,
|
|
7154
|
-
c("span",
|
|
7331
|
+
}, null, 8, ["name"])], 8, Vl),
|
|
7332
|
+
c("span", Hl, k(F(W.value)) + " / " + k(F(A(m))), 1),
|
|
7155
7333
|
r[7] ||= c("div", { class: "flex-1" }, null, -1),
|
|
7156
7334
|
c("button", {
|
|
7157
7335
|
type: "button",
|
|
@@ -7162,7 +7340,7 @@ var Ks = { render: Gs }, qs = { class: "flex items-center justify-end self-stret
|
|
|
7162
7340
|
name: A(h) ? "volume-xmark" : "volume-high",
|
|
7163
7341
|
class: "text-sm",
|
|
7164
7342
|
"aria-hidden": "true"
|
|
7165
|
-
}, null, 8, ["name"])], 8,
|
|
7343
|
+
}, null, 8, ["name"])], 8, Ul),
|
|
7166
7344
|
c("button", {
|
|
7167
7345
|
type: "button",
|
|
7168
7346
|
"aria-label": A(_) ? a.value.exitFullscreen : a.value.enterFullscreen,
|
|
@@ -7172,10 +7350,10 @@ var Ks = { render: Gs }, qs = { class: "flex items-center justify-end self-stret
|
|
|
7172
7350
|
name: A(_) ? "compress" : "expand",
|
|
7173
7351
|
class: "text-sm",
|
|
7174
7352
|
"aria-hidden": "true"
|
|
7175
|
-
}, null, 8, ["name"])], 8,
|
|
7353
|
+
}, null, 8, ["name"])], 8, Wl)
|
|
7176
7354
|
])], 4)) : o("", !0)
|
|
7177
7355
|
], 32));
|
|
7178
7356
|
}
|
|
7179
7357
|
});
|
|
7180
7358
|
//#endregion
|
|
7181
|
-
export { ct as EVENT_CONFIG_MAP, lt as NexxtAnimatedNumber, ht as NexxtAnnouncement, bt as NexxtAvatar, St as NexxtButton, en as NexxtCalendar, rn as NexxtCard, on as NexxtCheckbox, sn as NexxtChip, Sn as NexxtColorPicker, Un as NexxtCombobox, Hn as NexxtComboboxPanel, Xn as NexxtContactInfoCard, lr as NexxtCountrySelect, pr as NexxtCustomerJourneyTile, mr as NexxtDatePicker, Sr as NexxtDoughnutChart, Dr as NexxtDropdownButton, Kr as NexxtEditorAlignItems, ri as NexxtEditorBorder, oi as NexxtEditorColor, ci as NexxtEditorFlexDirection, mi as NexxtEditorGap, Ei as NexxtEditorHeadingType, Oi as NexxtEditorJustifyContent, ea as NexxtEditorPadding, aa as NexxtEditorRadius, $ as NexxtEditorSettingsBlock, sa as NexxtEditorTextAlign, ua as NexxtEnergyLabel, Q as NexxtFloatingPanel, ma as NexxtHeader, Z as NexxtIcon, ga as NexxtInfoBlock, kn as NexxtInputField, wa as NexxtInputSelect, Ea as NexxtLoader, Aa as NexxtModal, Ma as NexxtModalFooter, co as NexxtPageCard, mo as NexxtPageContainer, ro as NexxtPageMockup, go as NexxtPageTypeTile, _o as NexxtPagination, xo as NexxtPresenceIndicator, No as NexxtProgressBar, Wo as NexxtPropertyCard, zo as NexxtPropertyListing, os as NexxtReferenceCard, Ci as NexxtSelect, ls as NexxtSelectableOption, hs as NexxtSidebarMenuItem, _s as NexxtSkeleton, xs as NexxtSkeletonPropertyCard, Xr as NexxtSlider, ws as NexxtSocialIcons, Os as NexxtSocialMediaCustomTemplate, Ls as NexxtSocialMediaTemplate, Zs as NexxtSocialMediaType, uc as NexxtSource, _t as NexxtSquircle, dc as NexxtStepperHeader, kr as NexxtSwitch, vc as NexxtTabbedContent, jc as NexxtTable, mc as NexxtTabs, Gc as NexxtTemplateCard, Yc as NexxtTextarea, nl as NexxtTimelineEvent, ll as NexxtTimelineLanes, ml as NexxtTimelinePhaseblock, gl as NexxtTimelineTrack, Cl as NexxtToast, wl as NexxtToaster, Wr as NexxtToggleGroup, Ir as NexxtTooltip,
|
|
7359
|
+
export { ct as EVENT_CONFIG_MAP, lt as NexxtAnimatedNumber, ht as NexxtAnnouncement, bt as NexxtAvatar, St as NexxtButton, en as NexxtCalendar, rn as NexxtCard, on as NexxtCheckbox, sn as NexxtChip, Sn as NexxtColorPicker, Un as NexxtCombobox, Hn as NexxtComboboxPanel, Xn as NexxtContactInfoCard, lr as NexxtCountrySelect, pr as NexxtCustomerJourneyTile, mr as NexxtDatePicker, Sr as NexxtDoughnutChart, Dr as NexxtDropdownButton, Kr as NexxtEditorAlignItems, ri as NexxtEditorBorder, oi as NexxtEditorColor, ci as NexxtEditorFlexDirection, mi as NexxtEditorGap, Ei as NexxtEditorHeadingType, Oi as NexxtEditorJustifyContent, ea as NexxtEditorPadding, aa as NexxtEditorRadius, $ as NexxtEditorSettingsBlock, sa as NexxtEditorTextAlign, ua as NexxtEnergyLabel, Q as NexxtFloatingPanel, ma as NexxtHeader, Z as NexxtIcon, ga as NexxtInfoBlock, kn as NexxtInputField, wa as NexxtInputSelect, Ea as NexxtLoader, Aa as NexxtModal, Ma as NexxtModalFooter, co as NexxtPageCard, mo as NexxtPageContainer, ro as NexxtPageMockup, go as NexxtPageTypeTile, _o as NexxtPagination, xo as NexxtPresenceIndicator, No as NexxtProgressBar, Wo as NexxtPropertyCard, zo as NexxtPropertyListing, os as NexxtReferenceCard, Ci as NexxtSelect, ls as NexxtSelectableOption, hs as NexxtSidebarMenuItem, _s as NexxtSkeleton, xs as NexxtSkeletonPropertyCard, Xr as NexxtSlider, ws as NexxtSocialIcons, Os as NexxtSocialMediaCustomTemplate, Ls as NexxtSocialMediaTemplate, Zs as NexxtSocialMediaType, uc as NexxtSource, _t as NexxtSquircle, dc as NexxtStepperHeader, kr as NexxtSwitch, vc as NexxtTabbedContent, jc as NexxtTable, mc as NexxtTabs, Gc as NexxtTemplateCard, Yc as NexxtTextarea, nl as NexxtTimelineEvent, ll as NexxtTimelineLanes, ml as NexxtTimelinePhaseblock, gl as NexxtTimelineTrack, Cl as NexxtToast, wl as NexxtToaster, Wr as NexxtToggleGroup, Ir as NexxtTooltip, Ml as NexxtTree, Gl as NexxtVideoPlayer, X as PHASE_MAP, sc as SOURCE_MAP };
|
package/dist/nuxt.js
CHANGED
|
@@ -49,6 +49,7 @@ var s = {
|
|
|
49
49
|
NexxtTimelineLanes: "components/molecules/TimelineLanes/TimelineLanes.vue",
|
|
50
50
|
NexxtToast: "components/molecules/Toast/Toast.vue",
|
|
51
51
|
NexxtToggleGroup: "components/molecules/ToggleGroup/ToggleGroup.vue",
|
|
52
|
+
NexxtTree: "components/molecules/Tree/Tree.vue",
|
|
52
53
|
NexxtCalendar: "components/organisms/Calendar/Calendar.vue",
|
|
53
54
|
NexxtColorPicker: "components/organisms/ColorPicker/ColorPicker.vue",
|
|
54
55
|
NexxtCombobox: "components/organisms/Combobox/Combobox.vue",
|
package/package.json
CHANGED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed, nextTick, onMounted, ref, useTemplateRef, watch } from 'vue'
|
|
3
|
+
import { useResizeObserver } from '@vueuse/core'
|
|
4
|
+
import NexxtIcon, { type NexxtIconName } from '../../atoms/Icon/Icon.vue'
|
|
5
|
+
|
|
6
|
+
export interface NexxtTreeNode {
|
|
7
|
+
/** Unique within the tree; this is what `selected` and `collapsed` hold. */
|
|
8
|
+
id: string
|
|
9
|
+
label: string
|
|
10
|
+
icon?: NexxtIconName
|
|
11
|
+
/** A node with children gets a chevron and can be folded. */
|
|
12
|
+
children?: NexxtTreeNode[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface NexxtTreeProps {
|
|
16
|
+
/** The top-level nodes; nest `children` for deeper levels. */
|
|
17
|
+
nodes: NexxtTreeNode[]
|
|
18
|
+
/** Accessible name for the tree, e.g. the heading above it. */
|
|
19
|
+
label: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface Row {
|
|
23
|
+
node: NexxtTreeNode
|
|
24
|
+
depth: number
|
|
25
|
+
parentId: string | null
|
|
26
|
+
expandable: boolean
|
|
27
|
+
expanded: boolean
|
|
28
|
+
position: number
|
|
29
|
+
setSize: number
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
defineOptions({ name: 'NexxtTree' })
|
|
33
|
+
|
|
34
|
+
const props = defineProps<NexxtTreeProps>()
|
|
35
|
+
|
|
36
|
+
const selected = defineModel<string | null>('selected', { default: null })
|
|
37
|
+
/** Ids of the nodes whose children are hidden. Tracking the collapsed ones makes "everything open" the default. */
|
|
38
|
+
const collapsed = defineModel<string[]>('collapsed', { default: () => [] })
|
|
39
|
+
|
|
40
|
+
const INDENT = 22
|
|
41
|
+
|
|
42
|
+
const root = useTemplateRef<HTMLElement>('root')
|
|
43
|
+
const focusedId = ref<string | null>(null)
|
|
44
|
+
|
|
45
|
+
// The visible rows in document order; children of a collapsed node are left out
|
|
46
|
+
const rows = computed(() => {
|
|
47
|
+
const result: Row[] = []
|
|
48
|
+
|
|
49
|
+
const walk = (nodes: NexxtTreeNode[], depth: number, parentId: string | null) => {
|
|
50
|
+
nodes.forEach((node, index) => {
|
|
51
|
+
const expandable = !!node.children?.length
|
|
52
|
+
const expanded = expandable && !collapsed.value.includes(node.id)
|
|
53
|
+
|
|
54
|
+
result.push({
|
|
55
|
+
node,
|
|
56
|
+
depth,
|
|
57
|
+
parentId,
|
|
58
|
+
expandable,
|
|
59
|
+
expanded,
|
|
60
|
+
position: index + 1,
|
|
61
|
+
setSize: nodes.length,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
if (expanded) walk(node.children!, depth + 1, node.id)
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
walk(props.nodes, 0, null)
|
|
69
|
+
|
|
70
|
+
return result
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// A row is only highlighted while it is actually on screen; collapsing its parent fades the
|
|
74
|
+
// highlight out rather than dropping it, so reopening slides it back from the same spot
|
|
75
|
+
const selectionVisible = computed(
|
|
76
|
+
() => !!selected.value && rows.value.some((row) => row.node.id === selected.value),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
/** Geometry of the moving highlight, relative to the tree container. */
|
|
80
|
+
const highlight = ref({ top: 0, height: 0 })
|
|
81
|
+
const highlightElement = useTemplateRef<HTMLElement>('highlightElement')
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* How the highlight travels to its next spot. A selection arrives on the row it was clicked on,
|
|
85
|
+
* so it decelerates; a row change drags the highlight along with a row that is sliding under
|
|
86
|
+
* the `move` transition, so it has to use that transition's duration and curve or the two come
|
|
87
|
+
* apart on screen. The first render and layout corrections do not travel at all.
|
|
88
|
+
*/
|
|
89
|
+
const MOTION = {
|
|
90
|
+
none: '',
|
|
91
|
+
select: 'transition-[transform,opacity] duration-200 ease-out-strong',
|
|
92
|
+
move: 'transition-[transform,opacity] duration-200 ease-in-out-strong',
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const motion = ref<keyof typeof MOTION>('none')
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Matched on the dataset rather than in a selector, so an id never needs escaping. A row that is
|
|
99
|
+
* leaving keeps its id for another beat, but it is out of the flow — `absolute` marks it — and
|
|
100
|
+
* folding the same node straight back open would otherwise find that stale one.
|
|
101
|
+
*/
|
|
102
|
+
const rowElement = (id: string | null | undefined) =>
|
|
103
|
+
Array.from(root.value?.querySelectorAll<HTMLElement>('[data-tree-id]') ?? []).find(
|
|
104
|
+
(element) => element.dataset.treeId === id && !element.classList.contains('absolute'),
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
const updateHighlight = async () => {
|
|
108
|
+
await nextTick()
|
|
109
|
+
if (!root.value || !selectionVisible.value) return
|
|
110
|
+
|
|
111
|
+
const element = rowElement(selected.value)
|
|
112
|
+
|
|
113
|
+
if (element) highlight.value = { top: element.offsetTop, height: element.offsetHeight }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Reposition without animating, for the first render and for layout corrections. Reading the
|
|
118
|
+
* geometry makes the browser commit the new position while the transition is still off; the
|
|
119
|
+
* class coming back after that has nothing left to animate. Deliberately not `requestAnimationFrame`:
|
|
120
|
+
* that never fires while the tree sits in a hidden tab, which would leave it unable to animate.
|
|
121
|
+
*/
|
|
122
|
+
const jumpTo = async (reposition: () => Promise<void>) => {
|
|
123
|
+
const previous = motion.value
|
|
124
|
+
motion.value = 'none'
|
|
125
|
+
|
|
126
|
+
await reposition()
|
|
127
|
+
await nextTick()
|
|
128
|
+
root.value?.getBoundingClientRect()
|
|
129
|
+
|
|
130
|
+
motion.value = previous
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Rows above the selection can appear or disappear, so every row change is a reposition too
|
|
134
|
+
watch([selected, rows], ([id], [previousId]) => {
|
|
135
|
+
motion.value = id === previousId ? 'move' : 'select'
|
|
136
|
+
updateHighlight()
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
// A resize corrects the geometry — late webfonts, a narrower panel — so it never animates.
|
|
140
|
+
// Expanding and collapsing resizes the tree too, and there the highlight is mid-flight: forcing
|
|
141
|
+
// the geometry then cancels its transition and teleports it to the row's end position.
|
|
142
|
+
useResizeObserver(root, () => {
|
|
143
|
+
if (highlightElement.value?.getAnimations().length) return
|
|
144
|
+
|
|
145
|
+
jumpTo(updateHighlight)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
onMounted(() =>
|
|
149
|
+
jumpTo(async () => {
|
|
150
|
+
await updateHighlight()
|
|
151
|
+
// Fallback metrics put the rows at another height, which would animate once the real font lands
|
|
152
|
+
await document.fonts?.ready
|
|
153
|
+
await updateHighlight()
|
|
154
|
+
}),
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Children unfold from under their parent. They are inserted at their final spot, where the rows
|
|
159
|
+
* below them are still sliding down to make room, so each one starts stacked on the parent's
|
|
160
|
+
* bottom edge and travels to its slot on the same duration and curve as the `move` transition.
|
|
161
|
+
* Fading in is what keeps the stack readable: on the way out from under the parent the children
|
|
162
|
+
* cover each other and the rows below, so the label only comes up over the last stretch, once
|
|
163
|
+
* everything has all but landed. Inline rather than in `enter-active-class`, because the two
|
|
164
|
+
* properties need their own timing.
|
|
165
|
+
*/
|
|
166
|
+
const ENTER_TRANSITION = 'transform 200ms var(--ease-in-out-strong), opacity 80ms linear 120ms'
|
|
167
|
+
|
|
168
|
+
const onEnter = (element: Element) => {
|
|
169
|
+
const row = element as HTMLElement
|
|
170
|
+
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return
|
|
171
|
+
|
|
172
|
+
const parent = rowElement(
|
|
173
|
+
rows.value.find((item) => item.node.id === row.dataset.treeId)?.parentId,
|
|
174
|
+
)
|
|
175
|
+
const travel = parent ? row.offsetTop - (parent.offsetTop + parent.offsetHeight) : 0
|
|
176
|
+
|
|
177
|
+
row.style.transition = 'none'
|
|
178
|
+
row.style.transform = `translateY(${-travel}px)`
|
|
179
|
+
row.style.opacity = '0'
|
|
180
|
+
// Nothing to click on a row that is still on its way and cannot be read yet
|
|
181
|
+
row.style.pointerEvents = 'none'
|
|
182
|
+
|
|
183
|
+
// Commits the start of the travel while the transition is off, so only the way back animates
|
|
184
|
+
row.getBoundingClientRect()
|
|
185
|
+
|
|
186
|
+
row.style.transition = ENTER_TRANSITION
|
|
187
|
+
row.style.transform = ''
|
|
188
|
+
row.style.opacity = ''
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const onEnterDone = (element: Element) => {
|
|
192
|
+
const row = element as HTMLElement
|
|
193
|
+
|
|
194
|
+
row.style.transition = ''
|
|
195
|
+
row.style.pointerEvents = ''
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// One tab stop for the whole tree: the focused row, else the selected one, else the first
|
|
199
|
+
const tabStopId = computed(() => {
|
|
200
|
+
const ids = rows.value.map((row) => row.node.id)
|
|
201
|
+
|
|
202
|
+
if (focusedId.value && ids.includes(focusedId.value)) return focusedId.value
|
|
203
|
+
if (selected.value && ids.includes(selected.value)) return selected.value
|
|
204
|
+
|
|
205
|
+
return ids[0] ?? null
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
const toggle = (id: string) => {
|
|
209
|
+
collapsed.value = collapsed.value.includes(id)
|
|
210
|
+
? collapsed.value.filter((item) => item !== id)
|
|
211
|
+
: [...collapsed.value, id]
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const focusRow = async (id: string) => {
|
|
215
|
+
focusedId.value = id
|
|
216
|
+
await nextTick()
|
|
217
|
+
|
|
218
|
+
// Matched on the dataset rather than in a selector, so an id never needs escaping
|
|
219
|
+
Array.from(root.value?.querySelectorAll<HTMLElement>('[data-tree-id]') ?? [])
|
|
220
|
+
.find((element) => element.dataset.treeId === id)
|
|
221
|
+
?.focus()
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const onKeydown = (event: KeyboardEvent) => {
|
|
225
|
+
const index = rows.value.findIndex((row) => row.node.id === tabStopId.value)
|
|
226
|
+
const row = rows.value[index]
|
|
227
|
+
if (!row) return
|
|
228
|
+
|
|
229
|
+
const move = (target: Row | undefined) => {
|
|
230
|
+
if (target) focusRow(target.node.id)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
switch (event.key) {
|
|
234
|
+
case 'ArrowDown':
|
|
235
|
+
move(rows.value[index + 1])
|
|
236
|
+
break
|
|
237
|
+
case 'ArrowUp':
|
|
238
|
+
move(rows.value[index - 1])
|
|
239
|
+
break
|
|
240
|
+
case 'Home':
|
|
241
|
+
move(rows.value[0])
|
|
242
|
+
break
|
|
243
|
+
case 'End':
|
|
244
|
+
move(rows.value[rows.value.length - 1])
|
|
245
|
+
break
|
|
246
|
+
case 'ArrowRight':
|
|
247
|
+
if (row.expandable && !row.expanded) toggle(row.node.id)
|
|
248
|
+
else if (row.expanded) move(rows.value[index + 1])
|
|
249
|
+
break
|
|
250
|
+
case 'ArrowLeft':
|
|
251
|
+
if (row.expanded) toggle(row.node.id)
|
|
252
|
+
else if (row.parentId) focusRow(row.parentId)
|
|
253
|
+
break
|
|
254
|
+
case 'Enter':
|
|
255
|
+
case ' ':
|
|
256
|
+
selected.value = row.node.id
|
|
257
|
+
break
|
|
258
|
+
default:
|
|
259
|
+
return
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
event.preventDefault()
|
|
263
|
+
}
|
|
264
|
+
</script>
|
|
265
|
+
|
|
266
|
+
<template>
|
|
267
|
+
<div ref="root" role="tree" :aria-label="label" class="relative isolate" @keydown="onKeydown">
|
|
268
|
+
<!-- One highlight for the whole tree: selecting another row slides it instead of
|
|
269
|
+
repainting two backgrounds. Behind the rows, so their hover still reads. -->
|
|
270
|
+
<div
|
|
271
|
+
ref="highlightElement"
|
|
272
|
+
aria-hidden="true"
|
|
273
|
+
class="pointer-events-none absolute top-0 left-0 -z-10 w-full rounded-md bg-cornflower-blue-50 motion-reduce:transition-none"
|
|
274
|
+
:class="[MOTION[motion], selectionVisible ? 'opacity-100' : 'opacity-0']"
|
|
275
|
+
:style="{ transform: `translateY(${highlight.top}px)`, height: `${highlight.height}px` }"
|
|
276
|
+
data-tree-highlight
|
|
277
|
+
/>
|
|
278
|
+
|
|
279
|
+
<!-- A `group` keeps the tree/treeitem relation intact now that the rows sit one level
|
|
280
|
+
deeper. Leaving rows go absolute so the remaining ones slide up right away, and go
|
|
281
|
+
invisible with them: out of the flow they stack on the first one's spot while the rows
|
|
282
|
+
below slide over them, which read as a flash of doubled labels. Folding away is not a
|
|
283
|
+
departure worth animating — the rows sliding up under the parent tell the story. -->
|
|
284
|
+
<TransitionGroup
|
|
285
|
+
tag="div"
|
|
286
|
+
role="group"
|
|
287
|
+
leave-active-class="invisible absolute w-full transition-none!"
|
|
288
|
+
move-class="transition-transform duration-200 ease-in-out-strong motion-reduce:transition-none"
|
|
289
|
+
@enter="onEnter"
|
|
290
|
+
@after-enter="onEnterDone"
|
|
291
|
+
@enter-cancelled="onEnterDone"
|
|
292
|
+
>
|
|
293
|
+
<!-- Every row keeps `small-normal`: switching the selected one to semibold widened its
|
|
294
|
+
label, which made the text jump. Colour carries the selection instead. -->
|
|
295
|
+
<div
|
|
296
|
+
v-for="row in rows"
|
|
297
|
+
:key="row.node.id"
|
|
298
|
+
role="treeitem"
|
|
299
|
+
:aria-level="row.depth + 1"
|
|
300
|
+
:aria-posinset="row.position"
|
|
301
|
+
:aria-setsize="row.setSize"
|
|
302
|
+
:aria-selected="selected === row.node.id"
|
|
303
|
+
:aria-expanded="row.expandable ? row.expanded : undefined"
|
|
304
|
+
:tabindex="row.node.id === tabStopId ? 0 : -1"
|
|
305
|
+
:data-tree-id="row.node.id"
|
|
306
|
+
class="group mb-0.5 flex cursor-pointer items-center gap-1.5 rounded-md py-1 pr-2 small-normal transition-colors duration-150 select-none focus-visible:outline-2 focus-visible:outline-cornflower-blue-500 motion-reduce:transition-none"
|
|
307
|
+
:class="
|
|
308
|
+
selected === row.node.id ? 'text-cornflower-blue-600' : 'text-gray-800 hover:bg-gray-100'
|
|
309
|
+
"
|
|
310
|
+
:style="{ paddingLeft: `${row.depth * INDENT + 4}px` }"
|
|
311
|
+
@click="selected = row.node.id"
|
|
312
|
+
@focus="focusedId = row.node.id"
|
|
313
|
+
>
|
|
314
|
+
<!-- Out of the tab order: the arrow keys expand and collapse for keyboard users.
|
|
315
|
+
Stays grey on the selected row: the chevron is a control, not part of the label. -->
|
|
316
|
+
<button
|
|
317
|
+
v-if="row.expandable"
|
|
318
|
+
type="button"
|
|
319
|
+
tabindex="-1"
|
|
320
|
+
aria-hidden="true"
|
|
321
|
+
class="flex size-5 shrink-0 cursor-pointer items-center justify-center text-gray-400 transition-colors duration-150 group-hover:text-gray-600 hover:text-gray-600 motion-reduce:transition-none"
|
|
322
|
+
@click.stop="toggle(row.node.id)"
|
|
323
|
+
>
|
|
324
|
+
<NexxtIcon
|
|
325
|
+
name="chevron-down"
|
|
326
|
+
class="extra-small-normal transition-transform duration-150 ease-out motion-reduce:transition-none"
|
|
327
|
+
:class="!row.expanded && '-rotate-90'"
|
|
328
|
+
/>
|
|
329
|
+
</button>
|
|
330
|
+
<span v-else class="size-5 shrink-0" />
|
|
331
|
+
|
|
332
|
+
<NexxtIcon
|
|
333
|
+
v-if="row.node.icon"
|
|
334
|
+
:name="row.node.icon"
|
|
335
|
+
class="shrink-0 transition-colors duration-150 motion-reduce:transition-none"
|
|
336
|
+
:class="selected === row.node.id ? 'text-cornflower-blue-600' : 'text-gray-600'"
|
|
337
|
+
/>
|
|
338
|
+
<span class="truncate">{{ row.node.label }}</span>
|
|
339
|
+
</div>
|
|
340
|
+
</TransitionGroup>
|
|
341
|
+
</div>
|
|
342
|
+
</template>
|
package/src/components.json
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"NexxtTimelineLanes": "components/molecules/TimelineLanes/TimelineLanes.vue",
|
|
47
47
|
"NexxtToast": "components/molecules/Toast/Toast.vue",
|
|
48
48
|
"NexxtToggleGroup": "components/molecules/ToggleGroup/ToggleGroup.vue",
|
|
49
|
+
"NexxtTree": "components/molecules/Tree/Tree.vue",
|
|
49
50
|
"NexxtCalendar": "components/organisms/Calendar/Calendar.vue",
|
|
50
51
|
"NexxtColorPicker": "components/organisms/ColorPicker/ColorPicker.vue",
|
|
51
52
|
"NexxtCombobox": "components/organisms/Combobox/Combobox.vue",
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type {
|
|
|
18
18
|
NexxtPageCardSlots,
|
|
19
19
|
} from './components/molecules/PageCard/PageCard.vue'
|
|
20
20
|
export type { NexxtPageMockupType } from './components/molecules/PageMockup/PageMockup.vue'
|
|
21
|
+
export type { NexxtTreeNode, NexxtTreeProps } from './components/molecules/Tree/Tree.vue'
|
|
21
22
|
export type {
|
|
22
23
|
EditorAlignItemsMessages,
|
|
23
24
|
EditorAlignItemsValue,
|
|
@@ -137,4 +138,5 @@ export { default as NexxtToast } from './components/molecules/Toast/Toast.vue'
|
|
|
137
138
|
export { default as NexxtToaster } from './components/organisms/Toaster/Toaster.vue'
|
|
138
139
|
export { default as NexxtToggleGroup } from './components/molecules/ToggleGroup/ToggleGroup.vue'
|
|
139
140
|
export { default as NexxtTooltip } from './components/atoms/Tooltip/Tooltip.vue'
|
|
141
|
+
export { default as NexxtTree } from './components/molecules/Tree/Tree.vue'
|
|
140
142
|
export { default as NexxtVideoPlayer } from './components/organisms/VideoPlayer/VideoPlayer.vue'
|
|
@@ -49,4 +49,10 @@
|
|
|
49
49
|
|
|
50
50
|
--spacing-8xl: 100rem;
|
|
51
51
|
--spacing-full-width: 116rem; /* 1920px (full hd) minus the sidebar: max app width */
|
|
52
|
+
|
|
53
|
+
/* Motion easings. `ease-out-strong` decelerates hard: things that arrive or
|
|
54
|
+
settle into place. `ease-in-out-strong` for elements that move from one
|
|
55
|
+
spot to another. */
|
|
56
|
+
--ease-out-strong: cubic-bezier(0.23, 1, 0.32, 1);
|
|
57
|
+
--ease-in-out-strong: cubic-bezier(0.77, 0, 0.175, 1);
|
|
52
58
|
}
|