@shwfed/nuxt 0.1.12 → 0.1.15
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/module.json +2 -2
- package/dist/module.mjs +7 -1
- package/dist/runtime/components/app.d.vue.ts +13 -0
- package/dist/runtime/components/app.vue +9 -0
- package/dist/runtime/components/app.vue.d.ts +13 -0
- package/dist/runtime/components/table.d.vue.ts +59 -0
- package/dist/runtime/components/table.vue +456 -0
- package/dist/runtime/components/table.vue.d.ts +59 -0
- package/dist/runtime/components/tooltip.d.vue.ts +21 -0
- package/dist/runtime/components/tooltip.vue +48 -0
- package/dist/runtime/components/tooltip.vue.d.ts +21 -0
- package/dist/runtime/composables/useTableRenderers.d.ts +8 -0
- package/dist/runtime/composables/useTableRenderers.js +9 -0
- package/dist/runtime/plugins/cel/index.d.ts +15 -6
- package/dist/runtime/plugins/cel/index.js +11 -23
- package/dist/runtime/plugins/markdown/index.d.ts +8 -0
- package/dist/runtime/plugins/markdown/index.js +10 -2
- package/dist/runtime/table-renderers/builtins.d.ts +1 -0
- package/dist/runtime/table-renderers/builtins.js +404 -0
- package/dist/runtime/table-renderers/registry.d.ts +40 -0
- package/dist/runtime/table-renderers/registry.js +25 -0
- package/package.json +10 -5
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { useForwardPropsEmits } from "reka-ui";
|
|
3
|
+
import { Tooltip } from "reka-ui/namespaced";
|
|
4
|
+
const props = defineProps({
|
|
5
|
+
defaultOpen: { type: Boolean, required: false },
|
|
6
|
+
open: { type: Boolean, required: false },
|
|
7
|
+
delayDuration: { type: Number, required: false },
|
|
8
|
+
disableHoverableContent: { type: Boolean, required: false },
|
|
9
|
+
disableClosingTrigger: { type: Boolean, required: false },
|
|
10
|
+
disabled: { type: Boolean, required: false },
|
|
11
|
+
ignoreNonKeyboardFocus: { type: Boolean, required: false },
|
|
12
|
+
content: { type: String, required: false }
|
|
13
|
+
});
|
|
14
|
+
const emits = defineEmits(["update:open"]);
|
|
15
|
+
const forwarded = useForwardPropsEmits(props, emits);
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<Tooltip.Root v-bind="forwarded">
|
|
20
|
+
<Tooltip.Trigger as-child>
|
|
21
|
+
<slot />
|
|
22
|
+
</Tooltip.Trigger>
|
|
23
|
+
<Tooltip.Content
|
|
24
|
+
side="top"
|
|
25
|
+
align="center"
|
|
26
|
+
:class="[
|
|
27
|
+
'bg-white text-zinc-700 animate-in fade-in-0 zoom-in-95',
|
|
28
|
+
'data-[state=closed]:animate-out data-[state=closed]:fade-out-0',
|
|
29
|
+
'data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2',
|
|
30
|
+
'data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2',
|
|
31
|
+
'data-[side=top]:slide-in-from-bottom-2',
|
|
32
|
+
'z-1024 w-fit rounded border border-zinc-200 px-6 py-2 text-xs',
|
|
33
|
+
'text-balance shadow-md'
|
|
34
|
+
]"
|
|
35
|
+
>
|
|
36
|
+
<span
|
|
37
|
+
v-if="content"
|
|
38
|
+
v-html="content"
|
|
39
|
+
/>
|
|
40
|
+
<Tooltip.Arrow
|
|
41
|
+
:class="[
|
|
42
|
+
'bg-white fill-white size-2.5 translate-y-[calc(-50%)] rotate-45 rounded-[2px]',
|
|
43
|
+
'border-b border-r border-zinc-200'
|
|
44
|
+
]"
|
|
45
|
+
/>
|
|
46
|
+
</Tooltip.Content>
|
|
47
|
+
</Tooltip.Root>
|
|
48
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type TooltipRootProps } from 'reka-ui';
|
|
2
|
+
type __VLS_Props = TooltipRootProps & {
|
|
3
|
+
content?: string;
|
|
4
|
+
};
|
|
5
|
+
declare var __VLS_14: {};
|
|
6
|
+
type __VLS_Slots = {} & {
|
|
7
|
+
default?: (props: typeof __VLS_14) => any;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
|
+
"update:open": (value: boolean) => any;
|
|
11
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
|
+
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
13
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
17
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
18
|
+
new (): {
|
|
19
|
+
$slots: S;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import '../table-renderers/builtins.js';
|
|
2
|
+
import { getTableRenderer, resolveTableRenderer } from '../table-renderers/registry.js';
|
|
3
|
+
export { defineTableRenderer } from '../table-renderers/registry.js';
|
|
4
|
+
export type { TableRenderer, TableRendererCellArgs, TableRendererColumnDefOverrides, TableRendererConfigComponent, TableRendererHeaderArgs, TableRendererId, } from '../table-renderers/registry.js';
|
|
5
|
+
export declare function useTableRenderers(): {
|
|
6
|
+
getTableRenderer: typeof getTableRenderer;
|
|
7
|
+
resolveTableRenderer: typeof resolveTableRenderer;
|
|
8
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "../table-renderers/builtins";
|
|
2
|
+
import { getTableRenderer, resolveTableRenderer } from "../table-renderers/registry.js";
|
|
3
|
+
export { defineTableRenderer } from "../table-renderers/registry.js";
|
|
4
|
+
export function useTableRenderers() {
|
|
5
|
+
return {
|
|
6
|
+
getTableRenderer,
|
|
7
|
+
resolveTableRenderer
|
|
8
|
+
};
|
|
9
|
+
}
|
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Effect, Either } from 'effect';
|
|
1
|
+
import type { Context } from '@marcbachmann/cel-js';
|
|
3
2
|
declare const _default: import("#app").Plugin<{
|
|
4
3
|
dsl: {
|
|
5
|
-
check: (source: string) =>
|
|
6
|
-
|
|
4
|
+
check: (source: string) => import("@marcbachmann/cel-js").TypeCheckResult;
|
|
5
|
+
/**
|
|
6
|
+
* Synchronous evaluation for render-time usage (e.g. table accessors).
|
|
7
|
+
*
|
|
8
|
+
* Will throw `TypeError` / `EvaluationError` on failure.
|
|
9
|
+
*/
|
|
10
|
+
evaluate: <T>(source: string, context?: Context) => T;
|
|
7
11
|
};
|
|
8
12
|
}> & import("#app").ObjectPlugin<{
|
|
9
13
|
dsl: {
|
|
10
|
-
check: (source: string) =>
|
|
11
|
-
|
|
14
|
+
check: (source: string) => import("@marcbachmann/cel-js").TypeCheckResult;
|
|
15
|
+
/**
|
|
16
|
+
* Synchronous evaluation for render-time usage (e.g. table accessors).
|
|
17
|
+
*
|
|
18
|
+
* Will throw `TypeError` / `EvaluationError` on failure.
|
|
19
|
+
*/
|
|
20
|
+
evaluate: <T>(source: string, context?: Context) => T;
|
|
12
21
|
};
|
|
13
22
|
}>;
|
|
14
23
|
export default _default;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { defineNuxtPlugin } from "#app";
|
|
2
|
-
import { TypeError, EvaluationError } from "@marcbachmann/cel-js";
|
|
3
2
|
import defu from "defu";
|
|
4
|
-
import { Effect, Either } from "effect";
|
|
5
3
|
import { createEnvironment } from "./env.js";
|
|
6
4
|
export default defineNuxtPlugin(() => {
|
|
7
5
|
const env = createEnvironment();
|
|
@@ -9,28 +7,18 @@ export default defineNuxtPlugin(() => {
|
|
|
9
7
|
provide: {
|
|
10
8
|
dsl: {
|
|
11
9
|
check: (source) => {
|
|
12
|
-
|
|
13
|
-
if (result.valid) {
|
|
14
|
-
return Either.right(result.type);
|
|
15
|
-
} else {
|
|
16
|
-
return Either.left(result.error);
|
|
17
|
-
}
|
|
10
|
+
return env.check(source);
|
|
18
11
|
},
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
throw error;
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
})
|
|
12
|
+
/**
|
|
13
|
+
* Synchronous evaluation for render-time usage (e.g. table accessors).
|
|
14
|
+
*
|
|
15
|
+
* Will throw `TypeError` / `EvaluationError` on failure.
|
|
16
|
+
*/
|
|
17
|
+
evaluate: (source, context) => {
|
|
18
|
+
return env.evaluate(source, defu(context, {
|
|
19
|
+
now: /* @__PURE__ */ new Date()
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
34
22
|
}
|
|
35
23
|
}
|
|
36
24
|
};
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { md } from './md.js';
|
|
2
2
|
declare const _default: import("#app").Plugin<{
|
|
3
3
|
md: typeof md;
|
|
4
|
+
markdown: {
|
|
5
|
+
render: (source: string) => string;
|
|
6
|
+
renderInline: (source: string) => string;
|
|
7
|
+
};
|
|
4
8
|
}> & import("#app").ObjectPlugin<{
|
|
5
9
|
md: typeof md;
|
|
10
|
+
markdown: {
|
|
11
|
+
render: (source: string) => string;
|
|
12
|
+
renderInline: (source: string) => string;
|
|
13
|
+
};
|
|
6
14
|
}>;
|
|
7
15
|
export default _default;
|
|
@@ -14,12 +14,20 @@ export default defineNuxtPlugin((app) => {
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
beforeUpdate(el, v) {
|
|
17
|
-
|
|
17
|
+
if (["inline", "inline-flex", "inline-block"].includes(getComputedStyle(el).display)) {
|
|
18
|
+
el.innerHTML = engine.renderInline(v.value);
|
|
19
|
+
} else {
|
|
20
|
+
el.innerHTML = engine.render(v.value);
|
|
21
|
+
}
|
|
18
22
|
}
|
|
19
23
|
});
|
|
20
24
|
return {
|
|
21
25
|
provide: {
|
|
22
|
-
md
|
|
26
|
+
md,
|
|
27
|
+
markdown: {
|
|
28
|
+
render: (source) => engine.render(source),
|
|
29
|
+
renderInline: (source) => engine.renderInline(source)
|
|
30
|
+
}
|
|
23
31
|
}
|
|
24
32
|
};
|
|
25
33
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "vue/jsx-runtime";
|
|
2
|
+
import { Icon } from "@iconify/vue";
|
|
3
|
+
import { format as formatDate, isValid, toDate } from "date-fns";
|
|
4
|
+
import { defineComponent } from "vue";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { defineTableRenderer } from "./registry.js";
|
|
7
|
+
const JUSTIFY_CLASS = {
|
|
8
|
+
left: "justify-start",
|
|
9
|
+
center: "justify-center",
|
|
10
|
+
right: "justify-end"
|
|
11
|
+
};
|
|
12
|
+
const TableRendererTextConfig = defineComponent({
|
|
13
|
+
name: "TableRendererTextConfig",
|
|
14
|
+
props: {
|
|
15
|
+
modelValue: {
|
|
16
|
+
type: Object,
|
|
17
|
+
default: null
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
emits: ["update:modelValue"],
|
|
21
|
+
setup(props, { emit }) {
|
|
22
|
+
const value = () => props.modelValue ?? {};
|
|
23
|
+
const update = (patch) => {
|
|
24
|
+
emit("update:modelValue", { ...value(), ...patch });
|
|
25
|
+
};
|
|
26
|
+
return () => /* @__PURE__ */ jsxs("div", { class: "flex flex-col gap-3 text-sm text-zinc-700", children: [
|
|
27
|
+
/* @__PURE__ */ jsxs("label", { class: "flex items-center gap-2 select-none", children: [
|
|
28
|
+
/* @__PURE__ */ jsx(
|
|
29
|
+
"input",
|
|
30
|
+
{
|
|
31
|
+
type: "checkbox",
|
|
32
|
+
checked: Boolean(value().copyable),
|
|
33
|
+
onInput: (e) => {
|
|
34
|
+
if (e.target instanceof HTMLInputElement)
|
|
35
|
+
update({ copyable: e.target.checked });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
),
|
|
39
|
+
/* @__PURE__ */ jsx("span", { children: "Copyable" })
|
|
40
|
+
] }),
|
|
41
|
+
/* @__PURE__ */ jsxs("label", { class: "flex flex-col gap-1", children: [
|
|
42
|
+
/* @__PURE__ */ jsx("span", { class: "text-xs text-zinc-500", children: "Copy expression" }),
|
|
43
|
+
/* @__PURE__ */ jsx(
|
|
44
|
+
"input",
|
|
45
|
+
{
|
|
46
|
+
class: "border border-zinc-200 rounded px-2 py-1 text-sm",
|
|
47
|
+
placeholder: "CEL expression (row, index)",
|
|
48
|
+
value: value().copyExpression ?? "",
|
|
49
|
+
onInput: (e) => {
|
|
50
|
+
if (e.target instanceof HTMLInputElement)
|
|
51
|
+
update({ copyExpression: e.target.value || null });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
] }),
|
|
56
|
+
/* @__PURE__ */ jsxs("label", { class: "flex flex-col gap-1", children: [
|
|
57
|
+
/* @__PURE__ */ jsx("span", { class: "text-xs text-zinc-500", children: "Align" }),
|
|
58
|
+
/* @__PURE__ */ jsxs(
|
|
59
|
+
"select",
|
|
60
|
+
{
|
|
61
|
+
class: "border border-zinc-200 rounded px-2 py-1 text-sm bg-white",
|
|
62
|
+
value: value().align ?? "left",
|
|
63
|
+
onChange: (e) => {
|
|
64
|
+
if (e.target instanceof HTMLSelectElement) {
|
|
65
|
+
const v = e.target.value;
|
|
66
|
+
if (v === "left" || v === "center" || v === "right")
|
|
67
|
+
update({ align: v });
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
children: [
|
|
71
|
+
/* @__PURE__ */ jsx("option", { value: "left", children: "left" }),
|
|
72
|
+
/* @__PURE__ */ jsx("option", { value: "center", children: "center" }),
|
|
73
|
+
/* @__PURE__ */ jsx("option", { value: "right", children: "right" })
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
] })
|
|
78
|
+
] });
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
const TableRendererSelectionConfig = defineComponent({
|
|
82
|
+
name: "TableRendererSelectionConfig",
|
|
83
|
+
props: {
|
|
84
|
+
modelValue: {
|
|
85
|
+
type: Object,
|
|
86
|
+
default: null
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
emits: ["update:modelValue"],
|
|
90
|
+
setup(props, { emit }) {
|
|
91
|
+
const value = () => props.modelValue ?? {};
|
|
92
|
+
const update = (patch) => {
|
|
93
|
+
emit("update:modelValue", { ...value(), ...patch });
|
|
94
|
+
};
|
|
95
|
+
return () => /* @__PURE__ */ jsx("div", { class: "flex flex-col gap-3 text-sm text-zinc-700", children: /* @__PURE__ */ jsxs("label", { class: "flex items-center gap-2 select-none", children: [
|
|
96
|
+
/* @__PURE__ */ jsx(
|
|
97
|
+
"input",
|
|
98
|
+
{
|
|
99
|
+
type: "checkbox",
|
|
100
|
+
checked: Boolean(value().crossPage),
|
|
101
|
+
onInput: (e) => {
|
|
102
|
+
if (e.target instanceof HTMLInputElement)
|
|
103
|
+
update({ crossPage: e.target.checked });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
/* @__PURE__ */ jsx("span", { children: "Cross page select-all" })
|
|
108
|
+
] }) });
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
const TableRendererDateConfig = defineComponent({
|
|
112
|
+
name: "TableRendererDateConfig",
|
|
113
|
+
props: {
|
|
114
|
+
modelValue: {
|
|
115
|
+
type: Object,
|
|
116
|
+
default: null
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
emits: ["update:modelValue"],
|
|
120
|
+
setup(props, { emit }) {
|
|
121
|
+
const value = () => props.modelValue ?? {};
|
|
122
|
+
const update = (patch) => {
|
|
123
|
+
emit("update:modelValue", { ...value(), ...patch });
|
|
124
|
+
};
|
|
125
|
+
return () => /* @__PURE__ */ jsx("div", { class: "flex flex-col gap-3 text-sm text-zinc-700", children: /* @__PURE__ */ jsxs("label", { class: "flex flex-col gap-1", children: [
|
|
126
|
+
/* @__PURE__ */ jsx("span", { class: "text-xs text-zinc-500", children: "Format" }),
|
|
127
|
+
/* @__PURE__ */ jsx(
|
|
128
|
+
"input",
|
|
129
|
+
{
|
|
130
|
+
class: "border border-zinc-200 rounded px-2 py-1 text-sm",
|
|
131
|
+
placeholder: "yyyy-MM-dd",
|
|
132
|
+
value: value().format ?? "",
|
|
133
|
+
onInput: (e) => {
|
|
134
|
+
if (e.target instanceof HTMLInputElement)
|
|
135
|
+
update({ format: e.target.value });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
] }) });
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
const TableRendererMarkdownConfig = defineComponent({
|
|
143
|
+
name: "TableRendererMarkdownConfig",
|
|
144
|
+
props: {
|
|
145
|
+
modelValue: {
|
|
146
|
+
type: Object,
|
|
147
|
+
default: null
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
emits: ["update:modelValue"],
|
|
151
|
+
setup(props, { emit }) {
|
|
152
|
+
const value = () => props.modelValue ?? {};
|
|
153
|
+
const update = (patch) => {
|
|
154
|
+
emit("update:modelValue", { ...value(), ...patch });
|
|
155
|
+
};
|
|
156
|
+
return () => /* @__PURE__ */ jsx("div", { class: "flex flex-col gap-3 text-sm text-zinc-700", children: /* @__PURE__ */ jsxs("label", { class: "flex flex-col gap-1", children: [
|
|
157
|
+
/* @__PURE__ */ jsx("span", { class: "text-xs text-zinc-500", children: "Source" }),
|
|
158
|
+
/* @__PURE__ */ jsx(
|
|
159
|
+
"textarea",
|
|
160
|
+
{
|
|
161
|
+
class: "border border-zinc-200 rounded px-2 py-1 text-sm min-h-20",
|
|
162
|
+
placeholder: "Markdown source (leave empty to use cell value)",
|
|
163
|
+
value: value().source ?? "",
|
|
164
|
+
onInput: (e) => {
|
|
165
|
+
if (e.target instanceof HTMLTextAreaElement)
|
|
166
|
+
update({ source: e.target.value || void 0 });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
] }) });
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
const NoOptionsConfig = defineComponent({
|
|
174
|
+
name: "TableRendererNoOptionsConfig",
|
|
175
|
+
emits: ["update:modelValue"],
|
|
176
|
+
setup() {
|
|
177
|
+
return () => /* @__PURE__ */ jsx("div", { class: "text-xs text-zinc-500", children: "No options." });
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
defineTableRenderer(
|
|
181
|
+
"table.renderer.text",
|
|
182
|
+
{
|
|
183
|
+
copyable: z.boolean().default(false),
|
|
184
|
+
copyExpression: z.string().nullable().optional().default(null),
|
|
185
|
+
align: z.enum(["left", "center", "right"]).default("left")
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
cell: ({ ctx, options, helpers }) => {
|
|
189
|
+
const rawValue = ctx.cell.getValue();
|
|
190
|
+
const isEmpty = rawValue === void 0 || rawValue === null;
|
|
191
|
+
const align = isEmpty ? "center" : options.align ?? "left";
|
|
192
|
+
const justifyClass = JUSTIFY_CLASS[align];
|
|
193
|
+
const onCopy = async () => {
|
|
194
|
+
try {
|
|
195
|
+
let text = String(ctx.cell.getValue());
|
|
196
|
+
if (options.copyExpression && helpers.evaluate) {
|
|
197
|
+
text = String(helpers.evaluate(options.copyExpression, {
|
|
198
|
+
row: ctx.row.original,
|
|
199
|
+
index: BigInt(ctx.row.index)
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
await navigator.clipboard.writeText(text);
|
|
203
|
+
} catch (e) {
|
|
204
|
+
console.error(e);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
return /* @__PURE__ */ jsxs(
|
|
208
|
+
"span",
|
|
209
|
+
{
|
|
210
|
+
class: [
|
|
211
|
+
"relative w-full py-2 px-1 flex items-center text-xs",
|
|
212
|
+
"text-ellipsis overflow-hidden whitespace-nowrap group",
|
|
213
|
+
justifyClass,
|
|
214
|
+
isEmpty ? "font-mono text-zinc-300 select-none" : "text-zinc-600"
|
|
215
|
+
],
|
|
216
|
+
children: [
|
|
217
|
+
isEmpty ? "-" : String(rawValue),
|
|
218
|
+
options.copyable && !isEmpty ? /* @__PURE__ */ jsx(
|
|
219
|
+
"button",
|
|
220
|
+
{
|
|
221
|
+
type: "button",
|
|
222
|
+
class: [
|
|
223
|
+
"cursor-pointer absolute right-1 top-1/2 -translate-y-1/2 bg-white border",
|
|
224
|
+
"w-6 h-6 flex items-center justify-center group-hover:opacity-100 opacity-0",
|
|
225
|
+
"transition-all duration-180 rounded border-zinc-200 text-zinc-500",
|
|
226
|
+
"hover:border-[var(--primary)]/50 hover:text-[var(--primary)]/80 hover:bg-[var(--primary)]/10"
|
|
227
|
+
],
|
|
228
|
+
onClick: onCopy,
|
|
229
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "fluent:copy-20-regular" })
|
|
230
|
+
}
|
|
231
|
+
) : null
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
);
|
|
235
|
+
},
|
|
236
|
+
config: TableRendererTextConfig
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
defineTableRenderer(
|
|
240
|
+
"table.renderer.selection",
|
|
241
|
+
{
|
|
242
|
+
crossPage: z.boolean().default(false)
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
cell: ({ ctx }) => {
|
|
246
|
+
const isSingle = ctx.table.options.enableMultiRowSelection === false;
|
|
247
|
+
return /* @__PURE__ */ jsx("div", { class: "group w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsxs("label", { class: "flex items-center has-enabled:cursor-pointer has-disabled:cursor-not-allowed relative", children: [
|
|
248
|
+
/* @__PURE__ */ jsx(
|
|
249
|
+
"input",
|
|
250
|
+
{
|
|
251
|
+
id: `${ctx.column.id}-${ctx.row.id}`,
|
|
252
|
+
type: "checkbox",
|
|
253
|
+
disabled: !ctx.row.getCanSelect(),
|
|
254
|
+
checked: ctx.row.getIsSelected(),
|
|
255
|
+
class: [
|
|
256
|
+
"peer h-4 w-4 disabled:opacity-50 transition-colors duration-180 appearance-none",
|
|
257
|
+
"border border-zinc-200 not-checked-enabled-group-hover:border-zinc-300 not-checked-enabled-group-hover:bg-zinc-100 checked:border-[var(--primary)]",
|
|
258
|
+
isSingle ? "rounded-full" : "rounded"
|
|
259
|
+
],
|
|
260
|
+
onInput: (e) => ctx.row.getToggleSelectedHandler()(e)
|
|
261
|
+
}
|
|
262
|
+
),
|
|
263
|
+
isSingle ? /* @__PURE__ */ jsx("div", { class: "absolute inset-1 bg-[var(--primary)] pointer-events-none rounded-full peer-checked:opacity-100 opacity-0 transition-opacity duration-180" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
264
|
+
/* @__PURE__ */ jsx(
|
|
265
|
+
Icon,
|
|
266
|
+
{
|
|
267
|
+
icon: "fluent:checkmark-20-filled",
|
|
268
|
+
class: "peer-checked:opacity-100 opacity-0 text-white text-xs absolute z-1 -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2"
|
|
269
|
+
}
|
|
270
|
+
),
|
|
271
|
+
/* @__PURE__ */ jsx("div", { class: "absolute inset-0 bg-[var(--primary)] rounded pointer-events-none peer-checked:opacity-100 opacity-0 transition-opacity duration-180" })
|
|
272
|
+
] })
|
|
273
|
+
] }) });
|
|
274
|
+
},
|
|
275
|
+
header: ({ ctx, options }) => {
|
|
276
|
+
if (ctx.table.options.enableMultiRowSelection === false)
|
|
277
|
+
return null;
|
|
278
|
+
const crossPage = options.crossPage ?? false;
|
|
279
|
+
const indeterminate = crossPage ? ctx.table.getIsSomePageRowsSelected() : ctx.table.getIsSomeRowsSelected();
|
|
280
|
+
const checked = crossPage ? ctx.table.getIsAllPageRowsSelected() : ctx.table.getIsAllRowsSelected();
|
|
281
|
+
const onInput = crossPage ? ctx.table.getToggleAllPageRowsSelectedHandler() : ctx.table.getToggleAllRowsSelectedHandler();
|
|
282
|
+
return /* @__PURE__ */ jsx("div", { class: "inline-flex items-center", children: /* @__PURE__ */ jsxs("label", { class: "flex items-center cursor-pointer relative", children: [
|
|
283
|
+
/* @__PURE__ */ jsx(
|
|
284
|
+
"input",
|
|
285
|
+
{
|
|
286
|
+
id: `${ctx.column.id}-header`,
|
|
287
|
+
type: "checkbox",
|
|
288
|
+
checked,
|
|
289
|
+
class: [
|
|
290
|
+
"peer h-4 w-4 cursor-pointer transition-colors duration-180 appearance-none rounded",
|
|
291
|
+
"border border-[color-mix(in_srgb,var(--primary)_10%,#00000033)] not-checked-group-hover:border-[color-mix(in_srgb,var(--primary)_20%,#00000033)]",
|
|
292
|
+
"not-checked-group-hover:bg-[color-mix(in_srgb,var(--primary)_5%,#00000011)] checked:border-[var(--primary)] checked:bg-[var(--primary)]"
|
|
293
|
+
],
|
|
294
|
+
ref: (el) => {
|
|
295
|
+
if (el instanceof HTMLInputElement)
|
|
296
|
+
el.indeterminate = Boolean(indeterminate);
|
|
297
|
+
},
|
|
298
|
+
onInput: (e) => onInput(e)
|
|
299
|
+
}
|
|
300
|
+
),
|
|
301
|
+
/* @__PURE__ */ jsx("span", { class: "absolute text-white opacity-0 peer-checked:opacity-100 top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 pointer-events-none", children: /* @__PURE__ */ jsx(Icon, { icon: "fluent:checkmark-20-filled", class: "text-white text-xs" }) })
|
|
302
|
+
] }) });
|
|
303
|
+
},
|
|
304
|
+
config: TableRendererSelectionConfig,
|
|
305
|
+
columnDefOverrides: {
|
|
306
|
+
enableResizing: false
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
);
|
|
310
|
+
defineTableRenderer(
|
|
311
|
+
"table.renderer.expand",
|
|
312
|
+
{},
|
|
313
|
+
{
|
|
314
|
+
cell: ({ ctx }) => {
|
|
315
|
+
if (!ctx.row.getCanExpand())
|
|
316
|
+
return null;
|
|
317
|
+
return /* @__PURE__ */ jsx("div", { class: "group w-full h-full flex items-center justify-center text-zinc-700", children: /* @__PURE__ */ jsx(
|
|
318
|
+
"button",
|
|
319
|
+
{
|
|
320
|
+
type: "button",
|
|
321
|
+
class: "cursor-pointer bg-transparent",
|
|
322
|
+
onClick: () => ctx.row.getToggleExpandedHandler()(),
|
|
323
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: ctx.row.getIsExpanded() ? "fluent:subtract-square-20-regular" : "fluent:add-square-20-regular" })
|
|
324
|
+
}
|
|
325
|
+
) });
|
|
326
|
+
},
|
|
327
|
+
header: ({ ctx }) => /* @__PURE__ */ jsx("div", { class: "group w-full h-full flex items-center justify-center text-base text-zinc-700", children: /* @__PURE__ */ jsx(
|
|
328
|
+
"button",
|
|
329
|
+
{
|
|
330
|
+
type: "button",
|
|
331
|
+
class: "cursor-pointer bg-transparent",
|
|
332
|
+
onClick: (e) => ctx.table.getToggleAllRowsExpandedHandler()(e),
|
|
333
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: ctx.table.getIsAllRowsExpanded() ? "fluent:subtract-square-20-regular" : "fluent:add-square-20-regular" })
|
|
334
|
+
}
|
|
335
|
+
) }),
|
|
336
|
+
config: NoOptionsConfig
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
defineTableRenderer(
|
|
340
|
+
"table.renderer.money",
|
|
341
|
+
{},
|
|
342
|
+
{
|
|
343
|
+
cell: ({ ctx }) => {
|
|
344
|
+
const n = Number.parseFloat(String(ctx.cell.getValue()));
|
|
345
|
+
const isNan = Number.isNaN(n);
|
|
346
|
+
const formatted = isNan ? "-" : n.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
347
|
+
return /* @__PURE__ */ jsx(
|
|
348
|
+
"div",
|
|
349
|
+
{
|
|
350
|
+
class: [
|
|
351
|
+
"relative w-full py-2 px-1 flex items-center",
|
|
352
|
+
"text-xs font-mono",
|
|
353
|
+
isNan ? "justify-center text-zinc-300 select-none" : "justify-end text-zinc-600"
|
|
354
|
+
],
|
|
355
|
+
children: formatted
|
|
356
|
+
}
|
|
357
|
+
);
|
|
358
|
+
},
|
|
359
|
+
config: NoOptionsConfig
|
|
360
|
+
}
|
|
361
|
+
);
|
|
362
|
+
defineTableRenderer(
|
|
363
|
+
"table.renderer.date",
|
|
364
|
+
{
|
|
365
|
+
format: z.string().default("yyyy-MM-dd")
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
cell: ({ ctx, options }) => {
|
|
369
|
+
const value = ctx.cell.getValue();
|
|
370
|
+
let d = null;
|
|
371
|
+
try {
|
|
372
|
+
d = typeof value === "string" || typeof value === "number" || value instanceof Date ? toDate(value) : null;
|
|
373
|
+
} catch {
|
|
374
|
+
}
|
|
375
|
+
const date = isValid(d) ? d : null;
|
|
376
|
+
const formatted = date ? formatDate(date, options.format ?? "yyyy-MM-dd") : "-";
|
|
377
|
+
return /* @__PURE__ */ jsx(
|
|
378
|
+
"div",
|
|
379
|
+
{
|
|
380
|
+
class: [
|
|
381
|
+
"relative w-full py-2 px-1 flex items-center justify-center text-xs",
|
|
382
|
+
date ? "text-zinc-600" : "text-zinc-300 select-none"
|
|
383
|
+
],
|
|
384
|
+
children: formatted
|
|
385
|
+
}
|
|
386
|
+
);
|
|
387
|
+
},
|
|
388
|
+
config: TableRendererDateConfig
|
|
389
|
+
}
|
|
390
|
+
);
|
|
391
|
+
defineTableRenderer(
|
|
392
|
+
"table.renderer.markdown",
|
|
393
|
+
{
|
|
394
|
+
source: z.string().optional()
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
cell: ({ ctx, options, helpers }) => {
|
|
398
|
+
const source = options.source ?? String(ctx.cell.getValue());
|
|
399
|
+
const html = helpers.renderInline(source);
|
|
400
|
+
return /* @__PURE__ */ jsx("div", { class: "relative w-full py-2 px-1 flex items-center justify-center text-xs", children: /* @__PURE__ */ jsx("span", { class: "prose prose-zinc text-xs", innerHTML: html }) });
|
|
401
|
+
},
|
|
402
|
+
config: TableRendererMarkdownConfig
|
|
403
|
+
}
|
|
404
|
+
);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { CellContext, ColumnDef, HeaderContext, RowData } from '@tanstack/vue-table';
|
|
2
|
+
import type { VNodeChild } from 'vue';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
export type TableRendererId = string;
|
|
5
|
+
export type TableRendererColumnDefOverrides<TData extends RowData = unknown> = Partial<Pick<ColumnDef<TData, unknown>, 'enableResizing' | 'enableSorting' | 'enableMultiSort' | 'enablePinning' | 'size' | 'meta'>>;
|
|
6
|
+
export type TableRendererCellArgs<TData extends RowData, TValue, TOptions> = Readonly<{
|
|
7
|
+
ctx: CellContext<TData, TValue>;
|
|
8
|
+
options: TOptions;
|
|
9
|
+
helpers: Readonly<{
|
|
10
|
+
renderInline: (source: string) => string;
|
|
11
|
+
evaluate?: (source: string, context?: Record<string, unknown>) => unknown;
|
|
12
|
+
}>;
|
|
13
|
+
}>;
|
|
14
|
+
export type TableRendererHeaderArgs<TData extends RowData, TValue, TOptions> = Readonly<{
|
|
15
|
+
ctx: HeaderContext<TData, TValue>;
|
|
16
|
+
title?: string;
|
|
17
|
+
options: TOptions;
|
|
18
|
+
helpers: Readonly<{
|
|
19
|
+
renderInline: (source: string) => string;
|
|
20
|
+
evaluate?: (source: string, context?: Record<string, unknown>) => unknown;
|
|
21
|
+
}>;
|
|
22
|
+
}>;
|
|
23
|
+
export type TableRendererConfigComponent<_TOptions> = unknown;
|
|
24
|
+
export type TableRenderer<TOptions> = Readonly<{
|
|
25
|
+
id: TableRendererId;
|
|
26
|
+
optionsSchema: z.ZodType<TOptions>;
|
|
27
|
+
parseOptions: (input: unknown) => TOptions;
|
|
28
|
+
cell: (args: TableRendererCellArgs<unknown, unknown, TOptions>) => VNodeChild;
|
|
29
|
+
header?: (args: TableRendererHeaderArgs<unknown, unknown, TOptions>) => VNodeChild;
|
|
30
|
+
config?: TableRendererConfigComponent<TOptions>;
|
|
31
|
+
columnDefOverrides?: TableRendererColumnDefOverrides;
|
|
32
|
+
}>;
|
|
33
|
+
export declare function defineTableRenderer<const TShape extends z.ZodRawShape, const TOptions = z.infer<z.ZodObject<TShape>>>(id: TableRendererId, shape: TShape, impl: Readonly<{
|
|
34
|
+
cell: TableRenderer<TOptions>['cell'];
|
|
35
|
+
header?: TableRenderer<TOptions>['header'];
|
|
36
|
+
config?: TableRenderer<TOptions>['config'];
|
|
37
|
+
columnDefOverrides?: TableRenderer<TOptions>['columnDefOverrides'];
|
|
38
|
+
}>): TableRenderer<TOptions>;
|
|
39
|
+
export declare function getTableRenderer(id: TableRendererId): TableRenderer<unknown> | undefined;
|
|
40
|
+
export declare function resolveTableRenderer(id: TableRendererId): TableRenderer<unknown>;
|