@iris-ui-kit/vue 0.2.27 → 0.2.29
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/admin.cjs +11 -3
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.js +3 -3
- package/dist/behaviors.d.cts +2 -2
- package/dist/behaviors.d.ts +2 -2
- package/dist/{chunk-IAG64CHL.js → chunk-BVKOOTXG.js} +3 -3
- package/dist/chunk-BVKOOTXG.js.map +1 -0
- package/dist/{chunk-ASFDGYIR.js → chunk-EZUDM4TM.js} +13 -5
- package/dist/chunk-EZUDM4TM.js.map +1 -0
- package/dist/{chunk-UPC4GN3F.js → chunk-KAOPZNZF.js} +3 -3
- package/dist/chunk-KAOPZNZF.js.map +1 -0
- package/dist/{chunk-MO7AAXA6.js → chunk-KSJZLFAT.js} +6 -6
- package/dist/chunk-KSJZLFAT.js.map +1 -0
- package/dist/{chunk-XCNCIG2I.js → chunk-LQ2YAOYR.js} +11 -10
- package/dist/chunk-LQ2YAOYR.js.map +1 -0
- package/dist/{chunk-ZTPIXL7Q.js → chunk-OH4YSGFK.js} +3 -3
- package/dist/chunk-OH4YSGFK.js.map +1 -0
- package/dist/{chunk-TCAXRWT6.js → chunk-W3JMJVEK.js} +3 -3
- package/dist/chunk-W3JMJVEK.js.map +1 -0
- package/dist/{chunk-LWABTQCB.js → chunk-X5UOY4IV.js} +13 -9
- package/dist/chunk-X5UOY4IV.js.map +1 -0
- package/dist/{chunk-3547J6IN.js → chunk-X7Y35UUL.js} +3 -3
- package/dist/{chunk-3547J6IN.js.map → chunk-X7Y35UUL.js.map} +1 -1
- package/dist/error-boundary.cjs +1 -1
- package/dist/error-boundary.cjs.map +1 -1
- package/dist/error-boundary.js +2 -2
- package/dist/form.cjs +1 -1
- package/dist/form.cjs.map +1 -1
- package/dist/form.js +1 -1
- package/dist/i18n.cjs +1 -1
- package/dist/i18n.cjs.map +1 -1
- package/dist/i18n.js +1 -1
- package/dist/index.cjs +3462 -859
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +723 -283
- package/dist/index.d.ts +723 -283
- package/dist/index.js +3432 -846
- package/dist/index.js.map +1 -1
- package/dist/modal-utils.cjs +9 -8
- package/dist/modal-utils.cjs.map +1 -1
- package/dist/modal-utils.js +1 -1
- package/dist/provider.cjs +4 -4
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.js +4 -4
- package/dist/skeletons.cjs +11 -7
- package/dist/skeletons.cjs.map +1 -1
- package/dist/skeletons.d.cts +1 -1
- package/dist/skeletons.d.ts +1 -1
- package/dist/skeletons.js +2 -2
- package/dist/skins.cjs +1 -1
- package/dist/skins.cjs.map +1 -1
- package/dist/skins.js +1 -1
- package/dist/theme.cjs +1 -1
- package/dist/theme.cjs.map +1 -1
- package/dist/theme.js +1 -1
- package/package.json +11 -11
- package/dist/chunk-ASFDGYIR.js.map +0 -1
- package/dist/chunk-IAG64CHL.js.map +0 -1
- package/dist/chunk-LWABTQCB.js.map +0 -1
- package/dist/chunk-MO7AAXA6.js.map +0 -1
- package/dist/chunk-TCAXRWT6.js.map +0 -1
- package/dist/chunk-UPC4GN3F.js.map +0 -1
- package/dist/chunk-XCNCIG2I.js.map +0 -1
- package/dist/chunk-ZTPIXL7Q.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -55,7 +55,7 @@ function useDisposableScope() {
|
|
|
55
55
|
});
|
|
56
56
|
return scope;
|
|
57
57
|
}
|
|
58
|
-
var IrisThemeKey =
|
|
58
|
+
var IrisThemeKey = Symbol("IrisTheme");
|
|
59
59
|
var ThemeProvider = vue.defineComponent({
|
|
60
60
|
name: "IrisThemeProvider",
|
|
61
61
|
props: {
|
|
@@ -164,7 +164,7 @@ function useColorScheme() {
|
|
|
164
164
|
vue.onBeforeUnmount(stop);
|
|
165
165
|
return scheme;
|
|
166
166
|
}
|
|
167
|
-
var IrisSkinKey =
|
|
167
|
+
var IrisSkinKey = Symbol("IrisSkin");
|
|
168
168
|
var SkinProvider = vue.defineComponent({
|
|
169
169
|
name: "IrisSkinProvider",
|
|
170
170
|
props: {
|
|
@@ -243,7 +243,7 @@ function useMachine(machine, options = {}) {
|
|
|
243
243
|
);
|
|
244
244
|
return { state, send: machine.send };
|
|
245
245
|
}
|
|
246
|
-
var FormInjectionKey =
|
|
246
|
+
var FormInjectionKey = Symbol("IrisForm");
|
|
247
247
|
function useFormContext() {
|
|
248
248
|
const form = vue.inject(FormInjectionKey, null);
|
|
249
249
|
if (!form) {
|
|
@@ -367,7 +367,7 @@ function useFieldArray(name) {
|
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
// src/i18n/context.ts
|
|
370
|
-
var I18nInjectionKey =
|
|
370
|
+
var I18nInjectionKey = Symbol("IrisI18n");
|
|
371
371
|
|
|
372
372
|
// src/i18n/I18nProvider.ts
|
|
373
373
|
var IrisI18nProvider = vue.defineComponent({
|
|
@@ -917,6 +917,7 @@ var CSS2 = `
|
|
|
917
917
|
--iris-nav-item-padding-block: 8px;
|
|
918
918
|
--iris-nav-item-border-radius: var(--iris-radius-md, 6px);
|
|
919
919
|
--iris-nav-item-hover: var(--iris-surface-hover, var(--iris-surface));
|
|
920
|
+
--iris-nav-item-active-hover: color-mix(in srgb, var(--iris-primary) 88%, black);
|
|
920
921
|
--iris-nav-item-height: 34px;
|
|
921
922
|
display: flex;
|
|
922
923
|
flex-direction: column;
|
|
@@ -1022,6 +1023,13 @@ var CSS2 = `
|
|
|
1022
1023
|
font-weight: 600;
|
|
1023
1024
|
}
|
|
1024
1025
|
|
|
1026
|
+
/* active \u9879\u7684 hover \u53CD\u9988\uFF1Aprimary \u52A0\u6DF1\u53D8\u4F53\uFF08\u76AE\u80A4\u53EF\u7528
|
|
1027
|
+
--iris-nav-item-active-hover \u8986\u76D6\uFF09\uFF1B\u7279\u5F02\u5EA6\u9AD8\u4E8E :hover/:where \u89C4\u5219 */
|
|
1028
|
+
.iris-nav-menu-item[data-active='true']:hover,
|
|
1029
|
+
.iris-nav-menu-item[data-active='true'].is-hovered:not([disabled], .is-disabled) {
|
|
1030
|
+
background: var(--iris-nav-item-active-hover, color-mix(in srgb, var(--iris-primary) 88%, black));
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1025
1033
|
:where(.iris-nav-menu-item[data-active-trail='true']) {
|
|
1026
1034
|
color: var(--iris-primary);
|
|
1027
1035
|
font-weight: 600;
|
|
@@ -2005,7 +2013,7 @@ function useTabsNav(nav) {
|
|
|
2005
2013
|
}
|
|
2006
2014
|
|
|
2007
2015
|
// src/primitives/dropdown/context.ts
|
|
2008
|
-
var DropdownContextKey =
|
|
2016
|
+
var DropdownContextKey = Symbol("IrisDropdown");
|
|
2009
2017
|
|
|
2010
2018
|
// src/primitives/dropdown/Dropdown.ts
|
|
2011
2019
|
var IrisDropdown = vue.defineComponent({
|
|
@@ -3422,7 +3430,7 @@ function useUndoStack(options) {
|
|
|
3422
3430
|
}
|
|
3423
3431
|
|
|
3424
3432
|
// src/provider/context.ts
|
|
3425
|
-
var PluginStoreContextKey =
|
|
3433
|
+
var PluginStoreContextKey = Symbol("IrisPluginStore");
|
|
3426
3434
|
|
|
3427
3435
|
// src/provider/IrisProvider.ts
|
|
3428
3436
|
var DEFAULT_LOCALE = "en-US";
|
|
@@ -3683,15 +3691,18 @@ function installButtonStyles() {
|
|
|
3683
3691
|
var SIZE_STYLES = {
|
|
3684
3692
|
sm: {
|
|
3685
3693
|
padding: "var(--iris-padding-sm) var(--iris-padding-md)",
|
|
3686
|
-
fontSize: "var(--iris-font-size-xs, 12px)"
|
|
3694
|
+
fontSize: "var(--iris-font-size-xs, 12px)",
|
|
3695
|
+
minHeight: "var(--iris-control-height-sm, 28px)"
|
|
3687
3696
|
},
|
|
3688
3697
|
md: {
|
|
3689
3698
|
padding: "var(--iris-padding-sm) var(--iris-padding-lg)",
|
|
3690
|
-
fontSize: "var(--iris-font-size-md, 14px)"
|
|
3699
|
+
fontSize: "var(--iris-font-size-md, 14px)",
|
|
3700
|
+
minHeight: "var(--iris-control-height-md, 34px)"
|
|
3691
3701
|
},
|
|
3692
3702
|
lg: {
|
|
3693
3703
|
padding: "var(--iris-padding-md) var(--iris-padding-lg)",
|
|
3694
|
-
fontSize: "var(--iris-font-size-lg, 16px)"
|
|
3704
|
+
fontSize: "var(--iris-font-size-lg, 16px)",
|
|
3705
|
+
minHeight: "var(--iris-control-height-lg, 40px)"
|
|
3695
3706
|
}
|
|
3696
3707
|
};
|
|
3697
3708
|
var VARIANT_STYLES = {
|
|
@@ -3726,6 +3737,7 @@ function buildInlineStyle(variant, size) {
|
|
|
3726
3737
|
const base = { ...SIZE_STYLES[size], ...VARIANT_STYLES[variant] };
|
|
3727
3738
|
if (variant === "link") {
|
|
3728
3739
|
base.padding = "0";
|
|
3740
|
+
delete base.minHeight;
|
|
3729
3741
|
}
|
|
3730
3742
|
return base;
|
|
3731
3743
|
}
|
|
@@ -3827,7 +3839,7 @@ var IrisButton = vue.defineComponent({
|
|
|
3827
3839
|
});
|
|
3828
3840
|
|
|
3829
3841
|
// src/primitives/popover/context.ts
|
|
3830
|
-
var PopoverContextKey =
|
|
3842
|
+
var PopoverContextKey = Symbol("IrisPopover");
|
|
3831
3843
|
|
|
3832
3844
|
// src/primitives/popover/Popover.ts
|
|
3833
3845
|
var IrisPopover = vue.defineComponent({
|
|
@@ -3948,42 +3960,18 @@ var ANIM_DIALOG = "var(--iris-anim-dialog)";
|
|
|
3948
3960
|
var ANIM_POPOVER = "var(--iris-anim-popover)";
|
|
3949
3961
|
var ANIM_TOAST = "var(--iris-anim-toast)";
|
|
3950
3962
|
var ANIM_TOOLTIP = "var(--iris-anim-tooltip)";
|
|
3951
|
-
|
|
3952
|
-
if (installed4 || typeof document === "undefined") return;
|
|
3953
|
-
installed4 = true;
|
|
3954
|
-
if (document.getElementById(STYLE_ID2)) return;
|
|
3955
|
-
const style = document.createElement("style");
|
|
3956
|
-
style.id = STYLE_ID2;
|
|
3957
|
-
style.textContent = `
|
|
3963
|
+
var ANIMATION_CSS = `
|
|
3958
3964
|
:root {
|
|
3959
3965
|
--iris-anim-dialog: iris-dialog-in 150ms ease-out;
|
|
3960
3966
|
--iris-anim-popover: iris-popover-in 150ms ease-out;
|
|
3961
3967
|
--iris-anim-toast: iris-toast-in 200ms ease-out;
|
|
3962
3968
|
--iris-anim-tooltip: iris-tooltip-in 120ms ease-out;
|
|
3963
3969
|
}
|
|
3964
|
-
/*
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
* Fade-only keeps the entrance motion without touching positioning.
|
|
3970
|
-
*/
|
|
3971
|
-
@keyframes iris-dialog-in {
|
|
3972
|
-
from { opacity: 0; }
|
|
3973
|
-
to { opacity: 1; }
|
|
3974
|
-
}
|
|
3975
|
-
@keyframes iris-popover-in {
|
|
3976
|
-
from { opacity: 0; }
|
|
3977
|
-
to { opacity: 1; }
|
|
3978
|
-
}
|
|
3979
|
-
@keyframes iris-toast-in {
|
|
3980
|
-
from { opacity: 0; }
|
|
3981
|
-
to { opacity: 1; }
|
|
3982
|
-
}
|
|
3983
|
-
@keyframes iris-tooltip-in {
|
|
3984
|
-
from { opacity: 0; }
|
|
3985
|
-
to { opacity: 1; }
|
|
3986
|
-
}
|
|
3970
|
+
/* Fade-only keyframes preserve Floating UI's inline translate3d position. */
|
|
3971
|
+
@keyframes iris-dialog-in { from { opacity: 0; } to { opacity: 1; } }
|
|
3972
|
+
@keyframes iris-popover-in { from { opacity: 0; } to { opacity: 1; } }
|
|
3973
|
+
@keyframes iris-toast-in { from { opacity: 0; } to { opacity: 1; } }
|
|
3974
|
+
@keyframes iris-tooltip-in { from { opacity: 0; } to { opacity: 1; } }
|
|
3987
3975
|
@media (prefers-reduced-motion: reduce) {
|
|
3988
3976
|
:root {
|
|
3989
3977
|
--iris-anim-dialog: none;
|
|
@@ -3992,7 +3980,6 @@ function installFloatingAnimations() {
|
|
|
3992
3980
|
--iris-anim-tooltip: none;
|
|
3993
3981
|
}
|
|
3994
3982
|
}
|
|
3995
|
-
/* P4: global focus-visible ring for interactive controls */
|
|
3996
3983
|
[data-iris-tabs-trigger]:focus-visible,
|
|
3997
3984
|
[data-iris-switch]:focus-visible,
|
|
3998
3985
|
[data-iris-checkbox]:focus-visible,
|
|
@@ -4004,6 +3991,13 @@ function installFloatingAnimations() {
|
|
|
4004
3991
|
outline-offset: 2px;
|
|
4005
3992
|
}
|
|
4006
3993
|
`;
|
|
3994
|
+
function installFloatingAnimations() {
|
|
3995
|
+
if (installed4 || typeof document === "undefined") return;
|
|
3996
|
+
installed4 = true;
|
|
3997
|
+
if (document.getElementById(STYLE_ID2)) return;
|
|
3998
|
+
const style = document.createElement("style");
|
|
3999
|
+
style.id = STYLE_ID2;
|
|
4000
|
+
style.textContent = ANIMATION_CSS;
|
|
4007
4001
|
document.head.appendChild(style);
|
|
4008
4002
|
}
|
|
4009
4003
|
|
|
@@ -4176,12 +4170,12 @@ var IrisTooltip = vue.defineComponent({
|
|
|
4176
4170
|
const triggerListeners = {
|
|
4177
4171
|
onPointerenter: handleEnter,
|
|
4178
4172
|
onPointerleave: handleLeave,
|
|
4179
|
-
onFocus: (
|
|
4173
|
+
onFocus: () => {
|
|
4180
4174
|
if (!props.disabled) hi.open();
|
|
4181
|
-
}
|
|
4182
|
-
onBlur: (
|
|
4175
|
+
},
|
|
4176
|
+
onBlur: () => {
|
|
4183
4177
|
if (!props.disabled) hi.close();
|
|
4184
|
-
}
|
|
4178
|
+
}
|
|
4185
4179
|
};
|
|
4186
4180
|
const captureTriggerRef = (el) => {
|
|
4187
4181
|
triggerRef.value = el ?? null;
|
|
@@ -4250,7 +4244,7 @@ var IrisTooltip = vue.defineComponent({
|
|
|
4250
4244
|
});
|
|
4251
4245
|
|
|
4252
4246
|
// src/primitives/dialog/context.ts
|
|
4253
|
-
var DialogContextKey =
|
|
4247
|
+
var DialogContextKey = Symbol("IrisDialog");
|
|
4254
4248
|
|
|
4255
4249
|
// src/primitives/dialog/Dialog.ts
|
|
4256
4250
|
var IrisDialog = vue.defineComponent({
|
|
@@ -4376,9 +4370,8 @@ function getFocusable(root) {
|
|
|
4376
4370
|
(el) => !el.hasAttribute("disabled") && el.tabIndex !== -1
|
|
4377
4371
|
);
|
|
4378
4372
|
}
|
|
4379
|
-
function
|
|
4380
|
-
|
|
4381
|
-
const onKeyDown = (event) => {
|
|
4373
|
+
function createFocusTrapKeyHandler(options) {
|
|
4374
|
+
return (event) => {
|
|
4382
4375
|
if (!options.active.value || event.key !== "Tab") return;
|
|
4383
4376
|
const root = options.container.value;
|
|
4384
4377
|
if (!root) return;
|
|
@@ -4396,13 +4389,15 @@ function useFocusTrap(options) {
|
|
|
4396
4389
|
event.preventDefault();
|
|
4397
4390
|
last.focus();
|
|
4398
4391
|
}
|
|
4399
|
-
} else {
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
first.focus();
|
|
4403
|
-
}
|
|
4392
|
+
} else if (active === last || !root.contains(active)) {
|
|
4393
|
+
event.preventDefault();
|
|
4394
|
+
first.focus();
|
|
4404
4395
|
}
|
|
4405
4396
|
};
|
|
4397
|
+
}
|
|
4398
|
+
function useFocusTrap(options) {
|
|
4399
|
+
let previouslyFocused = null;
|
|
4400
|
+
const onKeyDown = createFocusTrapKeyHandler(options);
|
|
4406
4401
|
const activate = () => {
|
|
4407
4402
|
if (typeof document === "undefined") return;
|
|
4408
4403
|
previouslyFocused = document.activeElement ?? null;
|
|
@@ -4707,7 +4702,7 @@ var IrisDialogClose = vue.defineComponent({
|
|
|
4707
4702
|
});
|
|
4708
4703
|
|
|
4709
4704
|
// src/primitives/drawer/context.ts
|
|
4710
|
-
var DrawerContextKey =
|
|
4705
|
+
var DrawerContextKey = Symbol("IrisDrawer");
|
|
4711
4706
|
|
|
4712
4707
|
// src/primitives/drawer/Drawer.ts
|
|
4713
4708
|
var IrisDrawer = vue.defineComponent({
|
|
@@ -5091,11 +5086,11 @@ var IrisInput = vue.defineComponent({
|
|
|
5091
5086
|
display: "inline-flex",
|
|
5092
5087
|
alignItems: "center",
|
|
5093
5088
|
gap: "var(--iris-gap-sm)",
|
|
5094
|
-
background: "var(--iris-background)",
|
|
5089
|
+
background: props.readonly ? "var(--iris-surface)" : "var(--iris-background)",
|
|
5095
5090
|
color: "var(--iris-foreground)",
|
|
5096
5091
|
border: `1px solid ${borderColor}`,
|
|
5097
5092
|
borderRadius: "var(--iris-radius-md)",
|
|
5098
|
-
cursor: props.disabled ? "not-allowed" : "text",
|
|
5093
|
+
cursor: props.disabled ? "not-allowed" : props.readonly ? "default" : "text",
|
|
5099
5094
|
opacity: props.disabled ? "0.6" : "1",
|
|
5100
5095
|
transition: "border-color 120ms ease, box-shadow 120ms ease",
|
|
5101
5096
|
boxShadow,
|
|
@@ -5135,7 +5130,7 @@ var IrisInput = vue.defineComponent({
|
|
|
5135
5130
|
...attrs,
|
|
5136
5131
|
"data-iris-input": "",
|
|
5137
5132
|
"data-iris-input-size": props.size,
|
|
5138
|
-
"data-state": props.invalid ? "invalid" : focused.value ? "focused" : "idle",
|
|
5133
|
+
"data-state": props.invalid ? "invalid" : focused.value ? "focused" : props.readonly ? "readonly" : "idle",
|
|
5139
5134
|
style: {
|
|
5140
5135
|
...wrapperStyle.value,
|
|
5141
5136
|
...attrs.style ?? {}
|
|
@@ -6717,7 +6712,7 @@ var IrisCheckbox = vue.defineComponent({
|
|
|
6717
6712
|
);
|
|
6718
6713
|
}
|
|
6719
6714
|
});
|
|
6720
|
-
var RadioGroupKey =
|
|
6715
|
+
var RadioGroupKey = Symbol("IrisRadioGroup");
|
|
6721
6716
|
var IrisRadioGroup = vue.defineComponent({
|
|
6722
6717
|
name: "IrisRadioGroup",
|
|
6723
6718
|
props: {
|
|
@@ -7091,6 +7086,152 @@ var IrisList = vue.defineComponent({
|
|
|
7091
7086
|
);
|
|
7092
7087
|
}
|
|
7093
7088
|
});
|
|
7089
|
+
function renderVirtualSelectListbox({
|
|
7090
|
+
items,
|
|
7091
|
+
translate,
|
|
7092
|
+
listboxRef,
|
|
7093
|
+
onListKeyDown,
|
|
7094
|
+
virtualizer,
|
|
7095
|
+
state,
|
|
7096
|
+
activeIndex,
|
|
7097
|
+
multiple,
|
|
7098
|
+
selectedValues,
|
|
7099
|
+
currentValue,
|
|
7100
|
+
onSelect,
|
|
7101
|
+
rowHeight
|
|
7102
|
+
}) {
|
|
7103
|
+
const optionStyle = (selected, active, disabled) => ({
|
|
7104
|
+
display: "flex",
|
|
7105
|
+
alignItems: "center",
|
|
7106
|
+
gap: "var(--iris-gap-sm)",
|
|
7107
|
+
padding: "var(--iris-padding-sm, 6px) var(--iris-padding-md)",
|
|
7108
|
+
borderRadius: "var(--iris-radius-sm)",
|
|
7109
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
7110
|
+
opacity: disabled ? "0.5" : "1",
|
|
7111
|
+
fontSize: "var(--iris-font-size-md, 14px)",
|
|
7112
|
+
background: selected ? "var(--iris-surface-selected, rgba(99, 102, 241, 0.12))" : active ? "var(--iris-surface-hover)" : "transparent",
|
|
7113
|
+
color: "var(--iris-foreground)",
|
|
7114
|
+
fontWeight: selected ? "600" : "400",
|
|
7115
|
+
outline: "none"
|
|
7116
|
+
});
|
|
7117
|
+
const check = () => vue.h(
|
|
7118
|
+
"svg",
|
|
7119
|
+
{
|
|
7120
|
+
"aria-hidden": "true",
|
|
7121
|
+
width: "14",
|
|
7122
|
+
height: "14",
|
|
7123
|
+
viewBox: "0 0 24 24",
|
|
7124
|
+
fill: "none",
|
|
7125
|
+
stroke: "var(--iris-primary)",
|
|
7126
|
+
"stroke-width": "2.5",
|
|
7127
|
+
"stroke-linecap": "round",
|
|
7128
|
+
"stroke-linejoin": "round"
|
|
7129
|
+
},
|
|
7130
|
+
[vue.h("path", { d: "M20 6 9 17l-5-5" })]
|
|
7131
|
+
);
|
|
7132
|
+
return vue.h(
|
|
7133
|
+
"ul",
|
|
7134
|
+
{
|
|
7135
|
+
role: "listbox",
|
|
7136
|
+
"aria-label": translate("select.options"),
|
|
7137
|
+
"data-iris-list": "",
|
|
7138
|
+
ref: (el) => {
|
|
7139
|
+
listboxRef.value = el ?? null;
|
|
7140
|
+
},
|
|
7141
|
+
onKeydown: onListKeyDown,
|
|
7142
|
+
onScroll: (event) => {
|
|
7143
|
+
virtualizer?.setScroll(event.currentTarget.scrollTop);
|
|
7144
|
+
},
|
|
7145
|
+
style: {
|
|
7146
|
+
listStyle: "none",
|
|
7147
|
+
margin: "0",
|
|
7148
|
+
padding: "var(--iris-padding-sm)",
|
|
7149
|
+
display: "flex",
|
|
7150
|
+
flexDirection: "column",
|
|
7151
|
+
outline: "none",
|
|
7152
|
+
maxHeight: "240px",
|
|
7153
|
+
overflowY: "auto"
|
|
7154
|
+
}
|
|
7155
|
+
},
|
|
7156
|
+
items.length === 0 ? [
|
|
7157
|
+
vue.h(
|
|
7158
|
+
"li",
|
|
7159
|
+
{
|
|
7160
|
+
role: "presentation",
|
|
7161
|
+
"data-iris-list-state": "empty",
|
|
7162
|
+
"aria-live": "polite",
|
|
7163
|
+
style: {
|
|
7164
|
+
listStyle: "none",
|
|
7165
|
+
padding: "12px",
|
|
7166
|
+
textAlign: "center",
|
|
7167
|
+
color: "var(--iris-muted)",
|
|
7168
|
+
fontSize: "var(--iris-font-size-md, 14px)"
|
|
7169
|
+
}
|
|
7170
|
+
},
|
|
7171
|
+
translate("list.empty")
|
|
7172
|
+
)
|
|
7173
|
+
] : [
|
|
7174
|
+
vue.h("li", {
|
|
7175
|
+
role: "presentation",
|
|
7176
|
+
"aria-hidden": "true",
|
|
7177
|
+
"data-iris-select-spacer": "",
|
|
7178
|
+
"data-iris-select-spacer-type": "top",
|
|
7179
|
+
style: { height: `${state.value.offsetBefore}px` }
|
|
7180
|
+
}),
|
|
7181
|
+
...state.value.items.map((item) => {
|
|
7182
|
+
const option = items[item.index];
|
|
7183
|
+
if (!option) return null;
|
|
7184
|
+
const active = item.index === activeIndex.value;
|
|
7185
|
+
const selected = multiple ? selectedValues.value.includes(option.value) : option.value === currentValue.value;
|
|
7186
|
+
return vue.h(
|
|
7187
|
+
"li",
|
|
7188
|
+
{
|
|
7189
|
+
key: String(option.value ?? item.index),
|
|
7190
|
+
role: "option",
|
|
7191
|
+
tabindex: active ? 0 : -1,
|
|
7192
|
+
"aria-selected": selected ? "true" : "false",
|
|
7193
|
+
"aria-disabled": option.disabled ? "true" : void 0,
|
|
7194
|
+
"aria-setsize": items.length,
|
|
7195
|
+
"aria-posinset": item.index + 1,
|
|
7196
|
+
"data-iris-list-index": item.index,
|
|
7197
|
+
"data-iris-list-item": "",
|
|
7198
|
+
"data-state": selected ? "selected" : active ? "active" : "idle",
|
|
7199
|
+
onClick: option.disabled ? void 0 : () => {
|
|
7200
|
+
activeIndex.value = item.index;
|
|
7201
|
+
onSelect(option);
|
|
7202
|
+
},
|
|
7203
|
+
onFocus: () => {
|
|
7204
|
+
activeIndex.value = item.index;
|
|
7205
|
+
},
|
|
7206
|
+
onMouseenter: () => {
|
|
7207
|
+
activeIndex.value = item.index;
|
|
7208
|
+
},
|
|
7209
|
+
style: optionStyle(selected, active, !!option.disabled)
|
|
7210
|
+
},
|
|
7211
|
+
[
|
|
7212
|
+
vue.h(
|
|
7213
|
+
"span",
|
|
7214
|
+
{ style: { flex: "1", minWidth: "0" } },
|
|
7215
|
+
option.label ?? String(option.value)
|
|
7216
|
+
),
|
|
7217
|
+
selected ? check() : null
|
|
7218
|
+
]
|
|
7219
|
+
);
|
|
7220
|
+
}),
|
|
7221
|
+
vue.h("li", {
|
|
7222
|
+
role: "presentation",
|
|
7223
|
+
"aria-hidden": "true",
|
|
7224
|
+
"data-iris-select-spacer": "",
|
|
7225
|
+
"data-iris-select-spacer-type": "bottom",
|
|
7226
|
+
style: {
|
|
7227
|
+
height: `${state.value.totalSize - state.value.offsetBefore - state.value.items.length * rowHeight}px`
|
|
7228
|
+
}
|
|
7229
|
+
})
|
|
7230
|
+
]
|
|
7231
|
+
);
|
|
7232
|
+
}
|
|
7233
|
+
|
|
7234
|
+
// src/primitives/select/Select.ts
|
|
7094
7235
|
var IrisSelect = vue.defineComponent({
|
|
7095
7236
|
name: "IrisSelect",
|
|
7096
7237
|
inheritAttrs: false,
|
|
@@ -7328,138 +7469,6 @@ var IrisSelect = vue.defineComponent({
|
|
|
7328
7469
|
})
|
|
7329
7470
|
]
|
|
7330
7471
|
);
|
|
7331
|
-
const renderVirtualListbox = () => {
|
|
7332
|
-
const list = props.items;
|
|
7333
|
-
const optionStyle = (selected, active, disabled) => ({
|
|
7334
|
-
display: "flex",
|
|
7335
|
-
alignItems: "center",
|
|
7336
|
-
gap: "var(--iris-gap-sm)",
|
|
7337
|
-
padding: "var(--iris-padding-sm, 6px) var(--iris-padding-md)",
|
|
7338
|
-
borderRadius: "var(--iris-radius-sm)",
|
|
7339
|
-
cursor: disabled ? "not-allowed" : "pointer",
|
|
7340
|
-
opacity: disabled ? "0.5" : "1",
|
|
7341
|
-
fontSize: "var(--iris-font-size-md, 14px)",
|
|
7342
|
-
background: selected ? "var(--iris-surface-selected, rgba(99, 102, 241, 0.12))" : active ? "var(--iris-surface-hover)" : "transparent",
|
|
7343
|
-
color: "var(--iris-foreground)",
|
|
7344
|
-
fontWeight: selected ? "600" : "400",
|
|
7345
|
-
outline: "none"
|
|
7346
|
-
});
|
|
7347
|
-
const check = () => vue.h(
|
|
7348
|
-
"svg",
|
|
7349
|
-
{
|
|
7350
|
-
"aria-hidden": "true",
|
|
7351
|
-
width: "14",
|
|
7352
|
-
height: "14",
|
|
7353
|
-
viewBox: "0 0 24 24",
|
|
7354
|
-
fill: "none",
|
|
7355
|
-
stroke: "var(--iris-primary)",
|
|
7356
|
-
"stroke-width": "2.5",
|
|
7357
|
-
"stroke-linecap": "round",
|
|
7358
|
-
"stroke-linejoin": "round"
|
|
7359
|
-
},
|
|
7360
|
-
[vue.h("path", { d: "M20 6 9 17l-5-5" })]
|
|
7361
|
-
);
|
|
7362
|
-
return vue.h(
|
|
7363
|
-
"ul",
|
|
7364
|
-
{
|
|
7365
|
-
role: "listbox",
|
|
7366
|
-
"aria-label": t("select.options"),
|
|
7367
|
-
"data-iris-list": "",
|
|
7368
|
-
ref: (el) => {
|
|
7369
|
-
listboxRef.value = el ?? null;
|
|
7370
|
-
},
|
|
7371
|
-
onKeydown: onListKeyDown,
|
|
7372
|
-
onScroll: (e) => {
|
|
7373
|
-
v?.setScroll(e.currentTarget.scrollTop);
|
|
7374
|
-
},
|
|
7375
|
-
style: {
|
|
7376
|
-
listStyle: "none",
|
|
7377
|
-
margin: "0",
|
|
7378
|
-
padding: "var(--iris-padding-sm)",
|
|
7379
|
-
display: "flex",
|
|
7380
|
-
flexDirection: "column",
|
|
7381
|
-
outline: "none",
|
|
7382
|
-
maxHeight: "240px",
|
|
7383
|
-
overflowY: "auto"
|
|
7384
|
-
}
|
|
7385
|
-
},
|
|
7386
|
-
list.length === 0 ? [
|
|
7387
|
-
vue.h(
|
|
7388
|
-
"li",
|
|
7389
|
-
{
|
|
7390
|
-
role: "presentation",
|
|
7391
|
-
"data-iris-list-state": "empty",
|
|
7392
|
-
"aria-live": "polite",
|
|
7393
|
-
style: {
|
|
7394
|
-
listStyle: "none",
|
|
7395
|
-
padding: "12px",
|
|
7396
|
-
textAlign: "center",
|
|
7397
|
-
color: "var(--iris-muted)",
|
|
7398
|
-
fontSize: "var(--iris-font-size-md, 14px)"
|
|
7399
|
-
}
|
|
7400
|
-
},
|
|
7401
|
-
t("list.empty")
|
|
7402
|
-
)
|
|
7403
|
-
] : [
|
|
7404
|
-
vue.h("li", {
|
|
7405
|
-
role: "presentation",
|
|
7406
|
-
"aria-hidden": "true",
|
|
7407
|
-
"data-iris-select-spacer": "",
|
|
7408
|
-
"data-iris-select-spacer-type": "top",
|
|
7409
|
-
style: { height: `${vstate.value.offsetBefore}px` }
|
|
7410
|
-
}),
|
|
7411
|
-
...vstate.value.items.map((item) => {
|
|
7412
|
-
const opt = list[item.index];
|
|
7413
|
-
if (!opt) return null;
|
|
7414
|
-
const active = item.index === activeIndex.value;
|
|
7415
|
-
const selected = props.multiple ? selectedValues.value.includes(opt.value) : opt.value === currentValue.value;
|
|
7416
|
-
return vue.h(
|
|
7417
|
-
"li",
|
|
7418
|
-
{
|
|
7419
|
-
key: String(opt.value ?? item.index),
|
|
7420
|
-
role: "option",
|
|
7421
|
-
tabindex: active ? 0 : -1,
|
|
7422
|
-
"aria-selected": selected ? "true" : "false",
|
|
7423
|
-
"aria-disabled": opt.disabled ? "true" : void 0,
|
|
7424
|
-
"aria-setsize": list.length,
|
|
7425
|
-
"aria-posinset": item.index + 1,
|
|
7426
|
-
"data-iris-list-index": item.index,
|
|
7427
|
-
"data-iris-list-item": "",
|
|
7428
|
-
"data-state": selected ? "selected" : active ? "active" : "idle",
|
|
7429
|
-
onClick: opt.disabled ? void 0 : () => {
|
|
7430
|
-
activeIndex.value = item.index;
|
|
7431
|
-
onSelect(opt);
|
|
7432
|
-
},
|
|
7433
|
-
onFocus: () => {
|
|
7434
|
-
activeIndex.value = item.index;
|
|
7435
|
-
},
|
|
7436
|
-
onMouseenter: () => {
|
|
7437
|
-
activeIndex.value = item.index;
|
|
7438
|
-
},
|
|
7439
|
-
style: optionStyle(selected, active, !!opt.disabled)
|
|
7440
|
-
},
|
|
7441
|
-
[
|
|
7442
|
-
vue.h(
|
|
7443
|
-
"span",
|
|
7444
|
-
{ style: { flex: "1", minWidth: "0" } },
|
|
7445
|
-
opt.label ?? String(opt.value)
|
|
7446
|
-
),
|
|
7447
|
-
selected ? check() : null
|
|
7448
|
-
]
|
|
7449
|
-
);
|
|
7450
|
-
}),
|
|
7451
|
-
vue.h("li", {
|
|
7452
|
-
role: "presentation",
|
|
7453
|
-
"aria-hidden": "true",
|
|
7454
|
-
"data-iris-select-spacer": "",
|
|
7455
|
-
"data-iris-select-spacer-type": "bottom",
|
|
7456
|
-
style: {
|
|
7457
|
-
height: `${vstate.value.totalSize - vstate.value.offsetBefore - vstate.value.items.length * ROW_HEIGHT3}px`
|
|
7458
|
-
}
|
|
7459
|
-
})
|
|
7460
|
-
]
|
|
7461
|
-
);
|
|
7462
|
-
};
|
|
7463
7472
|
return () => vue.h(
|
|
7464
7473
|
IrisPopover,
|
|
7465
7474
|
{
|
|
@@ -7506,7 +7515,20 @@ var IrisSelect = vue.defineComponent({
|
|
|
7506
7515
|
style: { padding: "var(--iris-padding-sm)", minWidth: "180px" },
|
|
7507
7516
|
...props.teleport !== void 0 ? { teleport: props.teleport } : {}
|
|
7508
7517
|
},
|
|
7509
|
-
() => props.virtual ?
|
|
7518
|
+
() => props.virtual ? renderVirtualSelectListbox({
|
|
7519
|
+
items: props.items,
|
|
7520
|
+
translate: t,
|
|
7521
|
+
listboxRef,
|
|
7522
|
+
onListKeyDown,
|
|
7523
|
+
virtualizer: v,
|
|
7524
|
+
state: vstate,
|
|
7525
|
+
activeIndex,
|
|
7526
|
+
multiple: props.multiple,
|
|
7527
|
+
selectedValues,
|
|
7528
|
+
currentValue,
|
|
7529
|
+
onSelect,
|
|
7530
|
+
rowHeight: ROW_HEIGHT3
|
|
7531
|
+
}) : vue.h(IrisList, {
|
|
7510
7532
|
items: props.items,
|
|
7511
7533
|
modelValue: currentValue.value,
|
|
7512
7534
|
onSelect,
|
|
@@ -7968,8 +7990,8 @@ var IrisSkeleton = vue.defineComponent({
|
|
|
7968
7990
|
vue.onMounted(installSkeletonStyles);
|
|
7969
7991
|
const style = vue.computed(() => {
|
|
7970
7992
|
const w = props.width !== void 0 ? toCss(props.width) : defaultWidth(props.shape);
|
|
7971
|
-
const
|
|
7972
|
-
return { width: w, height:
|
|
7993
|
+
const h136 = props.height !== void 0 ? toCss(props.height) : defaultHeight(props.shape, props.width);
|
|
7994
|
+
return { width: w, height: h136 };
|
|
7973
7995
|
});
|
|
7974
7996
|
return () => vue.h("div", {
|
|
7975
7997
|
...attrs,
|
|
@@ -9080,7 +9102,7 @@ var IrisChip = vue.defineComponent({
|
|
|
9080
9102
|
});
|
|
9081
9103
|
|
|
9082
9104
|
// src/primitives/accordion/context.ts
|
|
9083
|
-
var AccordionContextKey =
|
|
9105
|
+
var AccordionContextKey = Symbol("IrisAccordion");
|
|
9084
9106
|
|
|
9085
9107
|
// src/primitives/accordion/Accordion.ts
|
|
9086
9108
|
var IrisAccordion = vue.defineComponent({
|
|
@@ -9318,7 +9340,7 @@ var IrisAccordionItem = vue.defineComponent({
|
|
|
9318
9340
|
});
|
|
9319
9341
|
|
|
9320
9342
|
// src/primitives/stepper/context.ts
|
|
9321
|
-
var StepperContextKey =
|
|
9343
|
+
var StepperContextKey = Symbol("IrisStepper");
|
|
9322
9344
|
|
|
9323
9345
|
// src/primitives/stepper/Stepper.ts
|
|
9324
9346
|
var IrisStepper = vue.defineComponent({
|
|
@@ -9566,7 +9588,7 @@ var IrisStepperStep = vue.defineComponent({
|
|
|
9566
9588
|
});
|
|
9567
9589
|
|
|
9568
9590
|
// src/primitives/toggle-group/context.ts
|
|
9569
|
-
var ToggleGroupContextKey =
|
|
9591
|
+
var ToggleGroupContextKey = Symbol("IrisToggleGroup");
|
|
9570
9592
|
var SIZE_PADDING = {
|
|
9571
9593
|
sm: "4px 10px",
|
|
9572
9594
|
md: "6px 14px",
|
|
@@ -10496,14 +10518,252 @@ var tableControlProps = {
|
|
|
10496
10518
|
default: void 0
|
|
10497
10519
|
}
|
|
10498
10520
|
};
|
|
10521
|
+
|
|
10522
|
+
// src/primitives/table/props.ts
|
|
10523
|
+
var tableProps = {
|
|
10524
|
+
columns: {
|
|
10525
|
+
type: Array,
|
|
10526
|
+
required: true
|
|
10527
|
+
},
|
|
10528
|
+
data: {
|
|
10529
|
+
type: Array,
|
|
10530
|
+
required: false,
|
|
10531
|
+
default: void 0
|
|
10532
|
+
},
|
|
10533
|
+
rowKey: { type: String, default: "id" },
|
|
10534
|
+
...tableControlProps,
|
|
10535
|
+
/** Multi-column sort (vxe sort-config.multiple parity). */
|
|
10536
|
+
multiSort: { type: Boolean, default: false },
|
|
10537
|
+
multiSortState: {
|
|
10538
|
+
type: Array,
|
|
10539
|
+
default: void 0
|
|
10540
|
+
},
|
|
10541
|
+
defaultMultiSort: {
|
|
10542
|
+
type: Array,
|
|
10543
|
+
default: void 0
|
|
10544
|
+
},
|
|
10545
|
+
striped: { type: Boolean, default: false },
|
|
10546
|
+
editConfig: {
|
|
10547
|
+
type: Object,
|
|
10548
|
+
default: void 0
|
|
10549
|
+
},
|
|
10550
|
+
bordered: { type: Boolean, default: true },
|
|
10551
|
+
/** Row-density preset; invalid runtime values fail closed to comfortable. */
|
|
10552
|
+
density: {
|
|
10553
|
+
type: String,
|
|
10554
|
+
default: "comfortable"
|
|
10555
|
+
},
|
|
10556
|
+
/** Show the local density cycle button in the table toolbar. */
|
|
10557
|
+
densityToggle: { type: Boolean, default: false },
|
|
10558
|
+
/** Show a live formatter preview while an editor is open. */
|
|
10559
|
+
editPreview: { type: Boolean, default: false },
|
|
10560
|
+
/** Highlight committed cells matching the active inline draft. */
|
|
10561
|
+
pattern: { type: Boolean, default: false },
|
|
10562
|
+
/** Alias for pattern feedback. */
|
|
10563
|
+
patternFill: { type: Boolean, default: false },
|
|
10564
|
+
/** Named snapshots available in the table toolbar. */
|
|
10565
|
+
views: { type: Object, default: void 0 },
|
|
10566
|
+
/** Controlled active named view notification. */
|
|
10567
|
+
onActiveViewChange: {
|
|
10568
|
+
type: Function,
|
|
10569
|
+
default: void 0
|
|
10570
|
+
},
|
|
10571
|
+
/** Optional tab strip; tab clicks apply listed view names in order. */
|
|
10572
|
+
tableTabs: { type: Array, default: void 0 },
|
|
10573
|
+
/** Show a draggable boundary for the leading left-pinned columns. */
|
|
10574
|
+
pinnedDrag: { type: Boolean, default: false },
|
|
10575
|
+
/** Called for each column whose pin side changes. */
|
|
10576
|
+
onColumnPinnedChange: {
|
|
10577
|
+
type: Function,
|
|
10578
|
+
default: void 0
|
|
10579
|
+
},
|
|
10580
|
+
/** Called once after a pinned-boundary commit. */
|
|
10581
|
+
onPinnedCountChange: { type: Function, default: void 0 },
|
|
10582
|
+
/** Infer leaf-column value kinds from the first non-empty data arrival and
|
|
10583
|
+
* fill only missing alignment defaults. Disabled by default. */
|
|
10584
|
+
autoDetectTypes: { type: Boolean, default: false },
|
|
10585
|
+
/** Below 480px, greedily hide the lowest-priority top-level columns until
|
|
10586
|
+
* the natural width fits; pinned columns survive. */
|
|
10587
|
+
responsive: { type: Boolean, default: false },
|
|
10588
|
+
/** Extra bare row sets appended as named CSV segments by the imperative handle. */
|
|
10589
|
+
exportNames: {
|
|
10590
|
+
type: Array,
|
|
10591
|
+
default: void 0
|
|
10592
|
+
},
|
|
10593
|
+
resizableColumns: { type: Boolean, default: false },
|
|
10594
|
+
columnWidths: {
|
|
10595
|
+
type: Object,
|
|
10596
|
+
default: void 0
|
|
10597
|
+
},
|
|
10598
|
+
virtualScroll: {
|
|
10599
|
+
type: Object,
|
|
10600
|
+
default: void 0
|
|
10601
|
+
},
|
|
10602
|
+
loading: { type: Boolean, default: false },
|
|
10603
|
+
error: { type: Boolean, default: false },
|
|
10604
|
+
/** Print-friendly mode: marks the root so toolbar/form chrome is hidden by print CSS. */
|
|
10605
|
+
printable: { type: Boolean, default: false },
|
|
10606
|
+
/** Show a confirmation preview before the toolbar CSV import callback. */
|
|
10607
|
+
importPreview: { type: Boolean, default: false },
|
|
10608
|
+
onRetry: { type: Function, default: void 0 },
|
|
10609
|
+
columnVirtualization: { type: Boolean, default: false },
|
|
10610
|
+
keyboardNavigation: { type: Boolean, default: false },
|
|
10611
|
+
cellRange: { type: Boolean, default: false },
|
|
10612
|
+
/** Range clipboard copy; copyWithFormat uses column formatter output. */
|
|
10613
|
+
clipConfig: { type: Object, default: void 0 },
|
|
10614
|
+
renderDetail: {
|
|
10615
|
+
type: Function,
|
|
10616
|
+
default: void 0
|
|
10617
|
+
},
|
|
10618
|
+
rowExpandable: {
|
|
10619
|
+
type: Function,
|
|
10620
|
+
default: void 0
|
|
10621
|
+
},
|
|
10622
|
+
defaultExpandedRowKeys: {
|
|
10623
|
+
type: Array,
|
|
10624
|
+
default: void 0
|
|
10625
|
+
},
|
|
10626
|
+
getSubRows: {
|
|
10627
|
+
type: Function,
|
|
10628
|
+
default: void 0
|
|
10629
|
+
},
|
|
10630
|
+
treeSelectionCascade: { type: Boolean, default: false },
|
|
10631
|
+
proxyConfig: {
|
|
10632
|
+
type: Object,
|
|
10633
|
+
default: void 0
|
|
10634
|
+
},
|
|
10635
|
+
formConfig: {
|
|
10636
|
+
type: Object,
|
|
10637
|
+
default: void 0
|
|
10638
|
+
},
|
|
10639
|
+
toolbar: {
|
|
10640
|
+
type: Object,
|
|
10641
|
+
default: void 0
|
|
10642
|
+
},
|
|
10643
|
+
columnVisibility: {
|
|
10644
|
+
type: Object,
|
|
10645
|
+
default: void 0
|
|
10646
|
+
},
|
|
10647
|
+
filters: {
|
|
10648
|
+
type: Object,
|
|
10649
|
+
default: void 0
|
|
10650
|
+
},
|
|
10651
|
+
filterValues: {
|
|
10652
|
+
type: Object,
|
|
10653
|
+
default: void 0
|
|
10654
|
+
},
|
|
10655
|
+
onFilterValuesChange: {
|
|
10656
|
+
type: Function,
|
|
10657
|
+
default: void 0
|
|
10658
|
+
},
|
|
10659
|
+
contextMenu: {
|
|
10660
|
+
type: Object,
|
|
10661
|
+
default: void 0
|
|
10662
|
+
},
|
|
10663
|
+
lazyLoad: {
|
|
10664
|
+
type: Function,
|
|
10665
|
+
default: void 0
|
|
10666
|
+
},
|
|
10667
|
+
seq: { type: Boolean, default: false },
|
|
10668
|
+
seqStartIndex: { type: Number, default: 1 },
|
|
10669
|
+
spanMethod: {
|
|
10670
|
+
type: Function,
|
|
10671
|
+
default: void 0
|
|
10672
|
+
},
|
|
10673
|
+
columnDrag: {
|
|
10674
|
+
type: Object,
|
|
10675
|
+
default: void 0
|
|
10676
|
+
},
|
|
10677
|
+
rowDrag: {
|
|
10678
|
+
type: Object,
|
|
10679
|
+
default: void 0
|
|
10680
|
+
},
|
|
10681
|
+
onDataChange: {
|
|
10682
|
+
type: Function,
|
|
10683
|
+
default: void 0
|
|
10684
|
+
}
|
|
10685
|
+
};
|
|
10686
|
+
var SELECTION_COL_WIDTH = 40;
|
|
10687
|
+
var EXPAND_COL_WIDTH = 40;
|
|
10688
|
+
var SEQ_COL_WIDTH = 40;
|
|
10689
|
+
var DRAG_COL_WIDTH = 40;
|
|
10690
|
+
var DEFAULT_COL_WIDTH = 140;
|
|
10691
|
+
var DEFAULT_MIN_WIDTH = 60;
|
|
10692
|
+
var RESIZE_STEP = 16;
|
|
10499
10693
|
function getCellValue(row, column) {
|
|
10500
10694
|
const key = column.dataIndex ?? column.key;
|
|
10501
10695
|
return row[key];
|
|
10502
10696
|
}
|
|
10503
|
-
|
|
10504
|
-
|
|
10505
|
-
|
|
10506
|
-
|
|
10697
|
+
function resolveSpan(occupied, rowIndex, columnIndex, method) {
|
|
10698
|
+
if (!method) return { rowspan: 1, colspan: 1 };
|
|
10699
|
+
const key = `${rowIndex}:${columnIndex}`;
|
|
10700
|
+
if (occupied.has(key)) return null;
|
|
10701
|
+
const span = method({ rowIndex, columnIndex });
|
|
10702
|
+
const rowspan = span?.rowspan ?? 1;
|
|
10703
|
+
const colspan = span?.colspan ?? 1;
|
|
10704
|
+
if (rowspan > 1) {
|
|
10705
|
+
for (let row = 1; row < rowspan; row += 1) occupied.add(`${rowIndex + row}:${columnIndex}`);
|
|
10706
|
+
}
|
|
10707
|
+
if (colspan > 1) {
|
|
10708
|
+
for (let column = 1; column < colspan; column += 1) {
|
|
10709
|
+
occupied.add(`${rowIndex}:${columnIndex + column}`);
|
|
10710
|
+
}
|
|
10711
|
+
}
|
|
10712
|
+
return { rowspan, colspan };
|
|
10713
|
+
}
|
|
10714
|
+
function resolveInitialWidth(col) {
|
|
10715
|
+
if (typeof col.width === "number") return col.width;
|
|
10716
|
+
if (typeof col.width === "string") {
|
|
10717
|
+
const match = col.width.match(/^(\d+(?:\.\d+)?)px$/);
|
|
10718
|
+
if (match) return Number(match[1]);
|
|
10719
|
+
}
|
|
10720
|
+
return DEFAULT_COL_WIDTH;
|
|
10721
|
+
}
|
|
10722
|
+
function computeVisibleColSet(enabled, columns, scrollLeft, viewportWidth, widths) {
|
|
10723
|
+
if (!enabled) return null;
|
|
10724
|
+
const range = core.computeVirtualRange({
|
|
10725
|
+
itemCount: columns.length,
|
|
10726
|
+
scrollTop: scrollLeft,
|
|
10727
|
+
viewportSize: viewportWidth,
|
|
10728
|
+
itemSize: (index) => widths[columns[index].key] ?? resolveInitialWidth(columns[index]),
|
|
10729
|
+
buffer: 2
|
|
10730
|
+
});
|
|
10731
|
+
const visible = /* @__PURE__ */ new Set();
|
|
10732
|
+
for (let index = range.startIndex; index <= range.endIndex; index += 1) visible.add(index);
|
|
10733
|
+
columns.forEach((column, index) => {
|
|
10734
|
+
if (column.pinned) visible.add(index);
|
|
10735
|
+
});
|
|
10736
|
+
return visible;
|
|
10737
|
+
}
|
|
10738
|
+
function cellId(rowIdent, columnKey) {
|
|
10739
|
+
return `${rowIdent}::${columnKey}`;
|
|
10740
|
+
}
|
|
10741
|
+
|
|
10742
|
+
// src/primitives/table/useTableSort.ts
|
|
10743
|
+
function buildSorter(col) {
|
|
10744
|
+
if (col.sorter) return col.sorter;
|
|
10745
|
+
return (a, b) => core.compareValues(getCellValue(a, col), getCellValue(b, col));
|
|
10746
|
+
}
|
|
10747
|
+
function buildMultiSortComparator(leafColumns, state) {
|
|
10748
|
+
if (state.length === 0) return null;
|
|
10749
|
+
const colMap = new Map(leafColumns.map((c) => [c.key, c]));
|
|
10750
|
+
const chain = [];
|
|
10751
|
+
for (const s of state) {
|
|
10752
|
+
const col = colMap.get(s.key);
|
|
10753
|
+
if (!col) continue;
|
|
10754
|
+
chain.push({ dir: s.direction === "asc" ? 1 : -1, sorter: buildSorter(col) });
|
|
10755
|
+
}
|
|
10756
|
+
if (chain.length === 0) return null;
|
|
10757
|
+
return (a, b) => {
|
|
10758
|
+
for (const step of chain) {
|
|
10759
|
+
const cmp = step.sorter(a, b);
|
|
10760
|
+
if (cmp !== 0) return cmp * step.dir;
|
|
10761
|
+
}
|
|
10762
|
+
return 0;
|
|
10763
|
+
};
|
|
10764
|
+
}
|
|
10765
|
+
function useTableSort(data, options) {
|
|
10766
|
+
const sortProp = vue.computed(() => options.sort === void 0 ? void 0 : vue.toValue(options.sort));
|
|
10507
10767
|
const internalSortValue = vue.ref(options.defaultSort ?? null);
|
|
10508
10768
|
const sortState = vue.computed({
|
|
10509
10769
|
get: () => sortProp.value === void 0 ? internalSortValue.value : sortProp.value ?? null,
|
|
@@ -10512,19 +10772,33 @@ function useTableSort(data, options) {
|
|
|
10512
10772
|
options.onSortChange?.(val);
|
|
10513
10773
|
}
|
|
10514
10774
|
});
|
|
10775
|
+
const multiEnabled = vue.computed(() => vue.toValue(options.multiSort) === true);
|
|
10776
|
+
const multiSortProp = vue.computed(
|
|
10777
|
+
() => options.multiSortState === void 0 ? void 0 : vue.toValue(options.multiSortState)
|
|
10778
|
+
);
|
|
10779
|
+
const internalMultiSort = vue.ref(options.defaultMultiSort ?? []);
|
|
10780
|
+
const multiSortState = vue.computed({
|
|
10781
|
+
get: () => multiSortProp.value === void 0 ? internalMultiSort.value : multiSortProp.value,
|
|
10782
|
+
set: (val) => {
|
|
10783
|
+
if (multiSortProp.value === void 0) internalMultiSort.value = val;
|
|
10784
|
+
options.onMultiSortChange?.(val);
|
|
10785
|
+
}
|
|
10786
|
+
});
|
|
10515
10787
|
const sortComparator = vue.computed(() => {
|
|
10516
10788
|
const s = sortState.value;
|
|
10517
10789
|
if (!s) return null;
|
|
10518
10790
|
const col = vue.toValue(options.leafColumns).find((c) => c.key === s.key);
|
|
10519
10791
|
if (!col) return null;
|
|
10520
10792
|
const dir = s.direction === "asc" ? 1 : -1;
|
|
10521
|
-
|
|
10522
|
-
return (a, b) => sorter(a, b) * dir;
|
|
10793
|
+
return (a, b) => buildSorter(col)(a, b) * dir;
|
|
10523
10794
|
});
|
|
10795
|
+
const multiSortComparator = vue.computed(
|
|
10796
|
+
() => buildMultiSortComparator(vue.toValue(options.leafColumns), multiSortState.value)
|
|
10797
|
+
);
|
|
10524
10798
|
const sortedData = vue.computed(() => {
|
|
10525
|
-
const
|
|
10526
|
-
if (!
|
|
10527
|
-
return [...data.value].sort(
|
|
10799
|
+
const comparator = multiEnabled.value ? multiSortComparator.value : sortComparator.value;
|
|
10800
|
+
if (!comparator) return data.value;
|
|
10801
|
+
return [...data.value].sort(comparator);
|
|
10528
10802
|
});
|
|
10529
10803
|
function setSort(next) {
|
|
10530
10804
|
if (sortProp.value === void 0) internalSortValue.value = next;
|
|
@@ -10541,172 +10815,1991 @@ function useTableSort(data, options) {
|
|
|
10541
10815
|
setSort({ key: col.key, direction: "desc" });
|
|
10542
10816
|
return;
|
|
10543
10817
|
}
|
|
10544
|
-
setSort(null);
|
|
10818
|
+
setSort(null);
|
|
10819
|
+
}
|
|
10820
|
+
function setMultiSort(next) {
|
|
10821
|
+
if (multiSortProp.value === void 0) internalMultiSort.value = next;
|
|
10822
|
+
options.onMultiSortChange?.(next);
|
|
10823
|
+
}
|
|
10824
|
+
function cycleMultiSort(col) {
|
|
10825
|
+
if (!col.sortable) return;
|
|
10826
|
+
const idx = multiSortState.value.findIndex((s) => s.key === col.key);
|
|
10827
|
+
if (idx < 0) {
|
|
10828
|
+
setMultiSort([...multiSortState.value, { key: col.key, direction: "asc" }]);
|
|
10829
|
+
return;
|
|
10830
|
+
}
|
|
10831
|
+
const next = [...multiSortState.value];
|
|
10832
|
+
if (next[idx].direction === "asc") {
|
|
10833
|
+
next[idx] = { key: col.key, direction: "desc" };
|
|
10834
|
+
setMultiSort(next);
|
|
10835
|
+
return;
|
|
10836
|
+
}
|
|
10837
|
+
next.splice(idx, 1);
|
|
10838
|
+
setMultiSort(next);
|
|
10839
|
+
}
|
|
10840
|
+
return {
|
|
10841
|
+
sortState,
|
|
10842
|
+
cycleSort,
|
|
10843
|
+
setSort,
|
|
10844
|
+
sortComparator,
|
|
10845
|
+
sortedData,
|
|
10846
|
+
multiSortState,
|
|
10847
|
+
cycleMultiSort,
|
|
10848
|
+
setMultiSort,
|
|
10849
|
+
multiSortComparator
|
|
10850
|
+
};
|
|
10851
|
+
}
|
|
10852
|
+
function mergeFilterValues(filters, filterValues) {
|
|
10853
|
+
const next = { ...filters };
|
|
10854
|
+
for (const [key, values] of Object.entries(filterValues)) {
|
|
10855
|
+
if (values.length > 0) next[key] = values.join(",");
|
|
10856
|
+
}
|
|
10857
|
+
return next;
|
|
10858
|
+
}
|
|
10859
|
+
function useTableProxy(options) {
|
|
10860
|
+
const cfg = vue.computed(() => vue.toValue(options.proxyConfig));
|
|
10861
|
+
const queryRef = vue.ref(void 0);
|
|
10862
|
+
vue.watch(
|
|
10863
|
+
() => cfg.value?.query,
|
|
10864
|
+
(query) => {
|
|
10865
|
+
queryRef.value = query;
|
|
10866
|
+
},
|
|
10867
|
+
{ immediate: true }
|
|
10868
|
+
);
|
|
10869
|
+
const proxy = vue.shallowRef(null);
|
|
10870
|
+
const state = vue.shallowRef({
|
|
10871
|
+
data: [],
|
|
10872
|
+
total: 0,
|
|
10873
|
+
loading: false,
|
|
10874
|
+
error: null,
|
|
10875
|
+
params: { page: 1, pageSize: 10, sort: null, filters: {} }
|
|
10876
|
+
});
|
|
10877
|
+
let unsubscribe = null;
|
|
10878
|
+
let mounted = false;
|
|
10879
|
+
const attach = (ctrl) => {
|
|
10880
|
+
unsubscribe?.();
|
|
10881
|
+
proxy.value = ctrl;
|
|
10882
|
+
state.value = ctrl.getState();
|
|
10883
|
+
unsubscribe = ctrl.subscribe((snapshot) => {
|
|
10884
|
+
state.value = snapshot;
|
|
10885
|
+
});
|
|
10886
|
+
};
|
|
10887
|
+
const detach = () => {
|
|
10888
|
+
unsubscribe?.();
|
|
10889
|
+
unsubscribe = null;
|
|
10890
|
+
proxy.value?.destroy();
|
|
10891
|
+
proxy.value = null;
|
|
10892
|
+
state.value = {
|
|
10893
|
+
data: [],
|
|
10894
|
+
total: 0,
|
|
10895
|
+
loading: false,
|
|
10896
|
+
error: null,
|
|
10897
|
+
params: { page: 1, pageSize: 10, sort: null, filters: {} }
|
|
10898
|
+
};
|
|
10899
|
+
};
|
|
10900
|
+
vue.watch(
|
|
10901
|
+
() => cfg.value === void 0,
|
|
10902
|
+
(absent) => {
|
|
10903
|
+
if (absent) {
|
|
10904
|
+
detach();
|
|
10905
|
+
return;
|
|
10906
|
+
}
|
|
10907
|
+
if (proxy.value) return;
|
|
10908
|
+
const config = cfg.value;
|
|
10909
|
+
const remoteSort = vue.toValue(options.remoteSort) === true;
|
|
10910
|
+
const remoteFilter = vue.toValue(options.remoteFilter) === true;
|
|
10911
|
+
const multiSort = vue.toValue(options.multiSort) === true;
|
|
10912
|
+
const ctrl = core.createRemoteTableSource({
|
|
10913
|
+
query: (params) => queryRef.value(params),
|
|
10914
|
+
autoLoad: false,
|
|
10915
|
+
initialParams: {
|
|
10916
|
+
page: config.defaultPage ?? 1,
|
|
10917
|
+
pageSize: config.pageSize ?? 10,
|
|
10918
|
+
sort: remoteSort ? vue.toValue(options.sort) ?? options.defaultSort ?? null : null,
|
|
10919
|
+
sorts: remoteSort && multiSort ? vue.toValue(options.multiSortState) ?? options.defaultMultiSort ?? [] : void 0,
|
|
10920
|
+
filters: remoteFilter ? mergeFilterValues(vue.toValue(options.filters) ?? {}, vue.toValue(options.filterValues) ?? {}) : {}
|
|
10921
|
+
}
|
|
10922
|
+
});
|
|
10923
|
+
attach(ctrl);
|
|
10924
|
+
if (mounted && config.autoLoad !== false) void ctrl.request();
|
|
10925
|
+
},
|
|
10926
|
+
{ immediate: true }
|
|
10927
|
+
);
|
|
10928
|
+
vue.onScopeDispose(detach);
|
|
10929
|
+
vue.onMounted(() => {
|
|
10930
|
+
mounted = true;
|
|
10931
|
+
const config = cfg.value;
|
|
10932
|
+
if (config && proxy.value && config.autoLoad !== false) void proxy.value.request();
|
|
10933
|
+
});
|
|
10934
|
+
const liveData = vue.shallowRef([]);
|
|
10935
|
+
vue.watch(
|
|
10936
|
+
state,
|
|
10937
|
+
(snapshot) => {
|
|
10938
|
+
liveData.value = snapshot.data;
|
|
10939
|
+
},
|
|
10940
|
+
{ immediate: true }
|
|
10941
|
+
);
|
|
10942
|
+
return {
|
|
10943
|
+
proxy: vue.computed(() => proxy.value),
|
|
10944
|
+
state: vue.computed(() => state.value),
|
|
10945
|
+
liveData,
|
|
10946
|
+
setParams: (partial) => proxy.value ? proxy.value.setParams(partial) : false,
|
|
10947
|
+
refetch: () => proxy.value ? proxy.value.refetch() : Promise.resolve()
|
|
10948
|
+
};
|
|
10949
|
+
}
|
|
10950
|
+
function exportCsv(rows, columns) {
|
|
10951
|
+
return core.toCsv(
|
|
10952
|
+
rows,
|
|
10953
|
+
columns.map((column) => ({
|
|
10954
|
+
key: column.key,
|
|
10955
|
+
title: column.title,
|
|
10956
|
+
dataIndex: typeof column.dataIndex === "string" ? column.dataIndex : void 0
|
|
10957
|
+
}))
|
|
10958
|
+
);
|
|
10959
|
+
}
|
|
10960
|
+
async function downloadCsv(filename, csv) {
|
|
10961
|
+
const BOM = String.fromCharCode(65279);
|
|
10962
|
+
await core.downloadFile({
|
|
10963
|
+
filename,
|
|
10964
|
+
content: BOM + csv,
|
|
10965
|
+
mimeType: "text/csv;charset=utf-8;"
|
|
10966
|
+
});
|
|
10967
|
+
}
|
|
10968
|
+
function renderFormSection(ctx) {
|
|
10969
|
+
const fc = ctx.formConfig;
|
|
10970
|
+
if (!fc) return null;
|
|
10971
|
+
return vue.h(
|
|
10972
|
+
"form",
|
|
10973
|
+
{
|
|
10974
|
+
"data-iris-table-form": "",
|
|
10975
|
+
onSubmit: (e) => {
|
|
10976
|
+
e.preventDefault();
|
|
10977
|
+
ctx.handleFormSubmit();
|
|
10978
|
+
},
|
|
10979
|
+
onReset: (e) => {
|
|
10980
|
+
e.preventDefault();
|
|
10981
|
+
ctx.handleFormReset();
|
|
10982
|
+
},
|
|
10983
|
+
style: {
|
|
10984
|
+
display: "flex",
|
|
10985
|
+
flexWrap: "wrap",
|
|
10986
|
+
alignItems: "flex-end",
|
|
10987
|
+
gap: "var(--iris-space-sm, 12px)",
|
|
10988
|
+
padding: "var(--iris-space-sm, 12px)",
|
|
10989
|
+
border: "1px solid var(--iris-border)",
|
|
10990
|
+
borderBottom: "none",
|
|
10991
|
+
background: "var(--iris-surface)",
|
|
10992
|
+
fontSize: "var(--iris-font-size-sm, 13px)"
|
|
10993
|
+
}
|
|
10994
|
+
},
|
|
10995
|
+
[
|
|
10996
|
+
...fc.fields.map(
|
|
10997
|
+
(field) => vue.h(
|
|
10998
|
+
"div",
|
|
10999
|
+
{
|
|
11000
|
+
key: field.key,
|
|
11001
|
+
"data-iris-table-form-field": field.key,
|
|
11002
|
+
style: { minWidth: 180 }
|
|
11003
|
+
},
|
|
11004
|
+
[
|
|
11005
|
+
vue.h(
|
|
11006
|
+
IrisFormField,
|
|
11007
|
+
{ label: field.label, size: "sm" },
|
|
11008
|
+
{
|
|
11009
|
+
default: () => field.type === "select" ? vue.h(IrisSelect, {
|
|
11010
|
+
items: (field.options ?? []).map((o) => ({
|
|
11011
|
+
value: o.value,
|
|
11012
|
+
label: o.label
|
|
11013
|
+
})),
|
|
11014
|
+
modelValue: ctx.formDraft.value[field.key] ?? "",
|
|
11015
|
+
placeholder: field.placeholder ?? ctx.t("select.placeholder"),
|
|
11016
|
+
size: "sm",
|
|
11017
|
+
"onUpdate:modelValue": (v) => ctx.setFormValue(field.key, String(v ?? ""))
|
|
11018
|
+
}) : vue.h(IrisInput, {
|
|
11019
|
+
modelValue: ctx.formDraft.value[field.key] ?? "",
|
|
11020
|
+
placeholder: field.placeholder,
|
|
11021
|
+
size: "sm",
|
|
11022
|
+
"onUpdate:modelValue": (v) => ctx.setFormValue(field.key, String(v ?? ""))
|
|
11023
|
+
})
|
|
11024
|
+
}
|
|
11025
|
+
)
|
|
11026
|
+
]
|
|
11027
|
+
)
|
|
11028
|
+
),
|
|
11029
|
+
vue.h("div", { style: { display: "flex", gap: "var(--iris-space-xs, 8px)" } }, [
|
|
11030
|
+
vue.h(
|
|
11031
|
+
IrisButton,
|
|
11032
|
+
{ type: "submit", size: "sm", "data-iris-table-form-submit": "" },
|
|
11033
|
+
{ default: () => fc.submitText ?? ctx.t("table.formSubmit") }
|
|
11034
|
+
),
|
|
11035
|
+
vue.h(
|
|
11036
|
+
IrisButton,
|
|
11037
|
+
{
|
|
11038
|
+
type: "reset",
|
|
11039
|
+
variant: "outline",
|
|
11040
|
+
size: "sm",
|
|
11041
|
+
"data-iris-table-form-reset": ""
|
|
11042
|
+
},
|
|
11043
|
+
{ default: () => fc.resetText ?? ctx.t("table.formReset") }
|
|
11044
|
+
)
|
|
11045
|
+
])
|
|
11046
|
+
]
|
|
11047
|
+
);
|
|
11048
|
+
}
|
|
11049
|
+
var toolbarBtnStyle = {
|
|
11050
|
+
border: "none",
|
|
11051
|
+
background: "transparent",
|
|
11052
|
+
cursor: "pointer",
|
|
11053
|
+
color: "var(--iris-muted)",
|
|
11054
|
+
fontSize: "var(--iris-font-size-md, 14px)"
|
|
11055
|
+
};
|
|
11056
|
+
function renderToolbarSection(ctx) {
|
|
11057
|
+
const tb = ctx.toolbar;
|
|
11058
|
+
if (!tb && !ctx.densityToggle) return null;
|
|
11059
|
+
const toolChildren = [];
|
|
11060
|
+
if (tb?.title) {
|
|
11061
|
+
toolChildren.push(
|
|
11062
|
+
vue.h("span", { style: { fontWeight: 600, color: "var(--iris-foreground)" } }, tb.title)
|
|
11063
|
+
);
|
|
11064
|
+
}
|
|
11065
|
+
toolChildren.push(vue.h("div", { style: { flex: "1" } }));
|
|
11066
|
+
if (tb?.onRefresh) {
|
|
11067
|
+
toolChildren.push(
|
|
11068
|
+
vue.h(
|
|
11069
|
+
"button",
|
|
11070
|
+
{
|
|
11071
|
+
type: "button",
|
|
11072
|
+
"data-iris-table-toolbar-refresh": "",
|
|
11073
|
+
"aria-label": ctx.t("table.refresh"),
|
|
11074
|
+
title: ctx.t("table.refresh"),
|
|
11075
|
+
onClick: () => {
|
|
11076
|
+
tb.onRefresh?.();
|
|
11077
|
+
void ctx.proxyCtrl.refetch();
|
|
11078
|
+
},
|
|
11079
|
+
style: toolbarBtnStyle
|
|
11080
|
+
},
|
|
11081
|
+
"\u21BB"
|
|
11082
|
+
)
|
|
11083
|
+
);
|
|
11084
|
+
}
|
|
11085
|
+
if (tb?.onExport) {
|
|
11086
|
+
toolChildren.push(
|
|
11087
|
+
vue.h(
|
|
11088
|
+
"button",
|
|
11089
|
+
{
|
|
11090
|
+
type: "button",
|
|
11091
|
+
"data-iris-table-toolbar-export": "",
|
|
11092
|
+
"aria-label": ctx.t("table.export"),
|
|
11093
|
+
title: ctx.t("table.export"),
|
|
11094
|
+
onClick: () => tb?.onExport?.(),
|
|
11095
|
+
style: toolbarBtnStyle
|
|
11096
|
+
},
|
|
11097
|
+
"\u21E9"
|
|
11098
|
+
)
|
|
11099
|
+
);
|
|
11100
|
+
}
|
|
11101
|
+
if (tb?.onImport) {
|
|
11102
|
+
toolChildren.push(
|
|
11103
|
+
vue.h("input", {
|
|
11104
|
+
ref: (el) => {
|
|
11105
|
+
ctx.importFileInput.value = el ?? null;
|
|
11106
|
+
},
|
|
11107
|
+
type: "file",
|
|
11108
|
+
accept: ".csv,text/csv",
|
|
11109
|
+
"data-iris-table-import-input": "",
|
|
11110
|
+
onChange: ctx.onImportFile,
|
|
11111
|
+
style: { display: "none" }
|
|
11112
|
+
}),
|
|
11113
|
+
vue.h(
|
|
11114
|
+
"button",
|
|
11115
|
+
{
|
|
11116
|
+
type: "button",
|
|
11117
|
+
"data-iris-table-toolbar-import": "",
|
|
11118
|
+
"aria-label": ctx.t("table.import"),
|
|
11119
|
+
title: ctx.t("table.import"),
|
|
11120
|
+
onClick: () => ctx.importFileInput.value?.click(),
|
|
11121
|
+
style: toolbarBtnStyle
|
|
11122
|
+
},
|
|
11123
|
+
"\u21EA"
|
|
11124
|
+
)
|
|
11125
|
+
);
|
|
11126
|
+
}
|
|
11127
|
+
if (tb?.batch && ctx.selectable === "multi" && ctx.displaySelection.value.length > 0) {
|
|
11128
|
+
toolChildren.push(
|
|
11129
|
+
vue.h(
|
|
11130
|
+
"button",
|
|
11131
|
+
{
|
|
11132
|
+
type: "button",
|
|
11133
|
+
"data-iris-table-toolbar-batch": "",
|
|
11134
|
+
"aria-label": tb.batch.label,
|
|
11135
|
+
title: tb.batch.label,
|
|
11136
|
+
onClick: () => tb.batch.onClick([...ctx.displaySelection.value]),
|
|
11137
|
+
style: {
|
|
11138
|
+
border: "none",
|
|
11139
|
+
cursor: "pointer",
|
|
11140
|
+
background: "var(--iris-primary)",
|
|
11141
|
+
color: "var(--iris-primary-foreground)",
|
|
11142
|
+
fontSize: "var(--iris-font-size-md, 14px)",
|
|
11143
|
+
display: "inline-flex",
|
|
11144
|
+
alignItems: "center",
|
|
11145
|
+
gap: "var(--iris-space-xxs, 4px)",
|
|
11146
|
+
padding: "var(--iris-space-xxs, 4px) var(--iris-space-xs, 8px)",
|
|
11147
|
+
borderRadius: "var(--iris-radius-sm, 4px)"
|
|
11148
|
+
}
|
|
11149
|
+
},
|
|
11150
|
+
[
|
|
11151
|
+
tb.batch.icon ? vue.h(
|
|
11152
|
+
"span",
|
|
11153
|
+
{ "aria-hidden": "true", style: { fontSize: "var(--iris-font-size-sm, 13px)" } },
|
|
11154
|
+
tb.batch.icon
|
|
11155
|
+
) : null,
|
|
11156
|
+
tb.batch.label
|
|
11157
|
+
]
|
|
11158
|
+
)
|
|
11159
|
+
);
|
|
11160
|
+
}
|
|
11161
|
+
if (tb?.buttons && tb.buttons.length > 0) {
|
|
11162
|
+
for (const btn of tb.buttons) {
|
|
11163
|
+
toolChildren.push(
|
|
11164
|
+
vue.h(
|
|
11165
|
+
"button",
|
|
11166
|
+
{
|
|
11167
|
+
key: btn.key,
|
|
11168
|
+
type: "button",
|
|
11169
|
+
"data-iris-table-toolbar-button": btn.key,
|
|
11170
|
+
[`data-iris-table-toolbar-button-${btn.key}`]: "",
|
|
11171
|
+
"aria-label": btn.label,
|
|
11172
|
+
title: btn.label,
|
|
11173
|
+
onClick: btn.onClick,
|
|
11174
|
+
style: {
|
|
11175
|
+
...toolbarBtnStyle,
|
|
11176
|
+
color: "var(--iris-foreground)",
|
|
11177
|
+
display: "inline-flex",
|
|
11178
|
+
alignItems: "center",
|
|
11179
|
+
gap: "var(--iris-space-xxs, 4px)",
|
|
11180
|
+
padding: "0 var(--iris-space-xxs, 4px)"
|
|
11181
|
+
}
|
|
11182
|
+
},
|
|
11183
|
+
[
|
|
11184
|
+
btn.icon ? vue.h(
|
|
11185
|
+
"span",
|
|
11186
|
+
{ "aria-hidden": "true", style: { fontSize: "var(--iris-font-size-sm, 13px)" } },
|
|
11187
|
+
btn.icon
|
|
11188
|
+
) : null,
|
|
11189
|
+
btn.label
|
|
11190
|
+
]
|
|
11191
|
+
)
|
|
11192
|
+
);
|
|
11193
|
+
}
|
|
11194
|
+
}
|
|
11195
|
+
if (ctx.densityToggle) {
|
|
11196
|
+
toolChildren.push(
|
|
11197
|
+
vue.h(
|
|
11198
|
+
"button",
|
|
11199
|
+
{
|
|
11200
|
+
type: "button",
|
|
11201
|
+
"data-iris-density-toggle": "",
|
|
11202
|
+
"data-iris-density": ctx.effectiveDensity,
|
|
11203
|
+
"aria-label": `${ctx.t("table.density")}: ${ctx.t(`table.density.${ctx.effectiveDensity}`)}`,
|
|
11204
|
+
title: `${ctx.t("table.density")}: ${ctx.t(`table.density.${ctx.effectiveDensity}`)}`,
|
|
11205
|
+
onClick: ctx.onDensityToggle,
|
|
11206
|
+
style: toolbarBtnStyle
|
|
11207
|
+
},
|
|
11208
|
+
ctx.t(`table.density.${ctx.effectiveDensity}`)
|
|
11209
|
+
)
|
|
11210
|
+
);
|
|
11211
|
+
}
|
|
11212
|
+
return vue.h(
|
|
11213
|
+
"div",
|
|
11214
|
+
{
|
|
11215
|
+
"data-iris-table-toolbar": "",
|
|
11216
|
+
style: {
|
|
11217
|
+
display: "flex",
|
|
11218
|
+
alignItems: "center",
|
|
11219
|
+
gap: "var(--iris-space-sm, 12px)",
|
|
11220
|
+
padding: "var(--iris-space-xs, 8px) var(--iris-space-sm, 12px)",
|
|
11221
|
+
border: "1px solid var(--iris-border)",
|
|
11222
|
+
borderBottom: "none",
|
|
11223
|
+
borderTopLeftRadius: "var(--iris-radius-md, 6px)",
|
|
11224
|
+
borderTopRightRadius: "var(--iris-radius-md, 6px)",
|
|
11225
|
+
background: "var(--iris-surface)",
|
|
11226
|
+
fontSize: "var(--iris-font-size-sm, 13px)"
|
|
11227
|
+
}
|
|
11228
|
+
},
|
|
11229
|
+
toolChildren
|
|
11230
|
+
);
|
|
11231
|
+
}
|
|
11232
|
+
function renderPagerSection(ctx) {
|
|
11233
|
+
if (!ctx.proxyCtrl.proxy.value) return null;
|
|
11234
|
+
const st = ctx.proxyCtrl.state.value;
|
|
11235
|
+
return vue.h(
|
|
11236
|
+
"div",
|
|
11237
|
+
{
|
|
11238
|
+
"data-iris-table-pager": "",
|
|
11239
|
+
style: {
|
|
11240
|
+
display: "flex",
|
|
11241
|
+
justifyContent: "flex-end",
|
|
11242
|
+
alignItems: "center",
|
|
11243
|
+
padding: "var(--iris-space-xs, 8px) var(--iris-space-sm, 12px)",
|
|
11244
|
+
borderTop: "1px solid var(--iris-border)",
|
|
11245
|
+
background: "var(--iris-surface)"
|
|
11246
|
+
}
|
|
11247
|
+
},
|
|
11248
|
+
[
|
|
11249
|
+
vue.h(IrisPagination, {
|
|
11250
|
+
modelValue: st.params.page,
|
|
11251
|
+
total: st.total,
|
|
11252
|
+
pageSize: st.params.pageSize,
|
|
11253
|
+
size: "sm",
|
|
11254
|
+
"onUpdate:modelValue": (page) => {
|
|
11255
|
+
ctx.proxyCtrl.setParams({ page });
|
|
11256
|
+
ctx.proxyConfig?.onPageChange?.(page, ctx.proxyCtrl.state.value.params.pageSize);
|
|
11257
|
+
}
|
|
11258
|
+
})
|
|
11259
|
+
]
|
|
11260
|
+
);
|
|
11261
|
+
}
|
|
11262
|
+
function renderContextMenuSection(ctx) {
|
|
11263
|
+
const st = ctx.state.value;
|
|
11264
|
+
if (!st || !st.open) return null;
|
|
11265
|
+
const node = vue.h(
|
|
11266
|
+
"div",
|
|
11267
|
+
{
|
|
11268
|
+
ref: (el) => {
|
|
11269
|
+
ctx.menuRef.value = el ?? null;
|
|
11270
|
+
},
|
|
11271
|
+
role: "menu",
|
|
11272
|
+
"data-iris-table-context-menu": "",
|
|
11273
|
+
style: {
|
|
11274
|
+
...ctx.styles.value,
|
|
11275
|
+
zIndex: "var(--iris-z-popover, 1000)",
|
|
11276
|
+
background: "var(--iris-surface-floating, var(--iris-surface))",
|
|
11277
|
+
color: "var(--iris-foreground)",
|
|
11278
|
+
border: "1px solid var(--iris-border)",
|
|
11279
|
+
borderRadius: "var(--iris-radius-md, 6px)",
|
|
11280
|
+
boxShadow: "var(--iris-shadow-lg)",
|
|
11281
|
+
padding: "var(--iris-space-xxs, 4px)",
|
|
11282
|
+
minWidth: "160px",
|
|
11283
|
+
display: "flex",
|
|
11284
|
+
flexDirection: "column"
|
|
11285
|
+
}
|
|
11286
|
+
},
|
|
11287
|
+
st.items.map(
|
|
11288
|
+
(item) => vue.h(
|
|
11289
|
+
"button",
|
|
11290
|
+
{
|
|
11291
|
+
key: item.key,
|
|
11292
|
+
type: "button",
|
|
11293
|
+
role: "menuitem",
|
|
11294
|
+
"data-iris-table-context-menu-item": item.key,
|
|
11295
|
+
disabled: item.disabled,
|
|
11296
|
+
"aria-disabled": item.disabled ? "true" : void 0,
|
|
11297
|
+
onClick: () => {
|
|
11298
|
+
ctx.contextMenu.onSelect(item.key, st.params);
|
|
11299
|
+
ctx.close();
|
|
11300
|
+
},
|
|
11301
|
+
style: {
|
|
11302
|
+
border: "none",
|
|
11303
|
+
background: "transparent",
|
|
11304
|
+
cursor: item.disabled ? "default" : "pointer",
|
|
11305
|
+
color: item.disabled ? "var(--iris-muted)" : "var(--iris-foreground)",
|
|
11306
|
+
font: "inherit",
|
|
11307
|
+
textAlign: "start",
|
|
11308
|
+
padding: "var(--iris-space-xxs, 4px) var(--iris-space-sm, 12px)",
|
|
11309
|
+
borderRadius: "var(--iris-radius-sm, 4px)"
|
|
11310
|
+
}
|
|
11311
|
+
},
|
|
11312
|
+
item.label
|
|
11313
|
+
)
|
|
11314
|
+
)
|
|
11315
|
+
);
|
|
11316
|
+
return vue.h(vue.Teleport, { to: "body" }, [node]);
|
|
11317
|
+
}
|
|
11318
|
+
function renderFilterPanelSection(ctx) {
|
|
11319
|
+
const st = ctx.state.value;
|
|
11320
|
+
if (!st || !st.open) return null;
|
|
11321
|
+
const col = ctx.columns.find((c) => c.key === st.colKey);
|
|
11322
|
+
if (!col || !col.filterable) return null;
|
|
11323
|
+
const options = col.filterOptions ?? [];
|
|
11324
|
+
const node = vue.h(
|
|
11325
|
+
"div",
|
|
11326
|
+
{
|
|
11327
|
+
ref: (el) => {
|
|
11328
|
+
ctx.panelRef.value = el ?? null;
|
|
11329
|
+
},
|
|
11330
|
+
role: "dialog",
|
|
11331
|
+
"aria-label": ctx.t("table.filter"),
|
|
11332
|
+
"data-iris-table-filter-panel": "",
|
|
11333
|
+
"data-iris-table-filter-column": st.colKey,
|
|
11334
|
+
style: {
|
|
11335
|
+
...ctx.styles.value,
|
|
11336
|
+
zIndex: "var(--iris-z-popover, 1000)",
|
|
11337
|
+
background: "var(--iris-surface-floating, var(--iris-surface))",
|
|
11338
|
+
color: "var(--iris-foreground)",
|
|
11339
|
+
border: "1px solid var(--iris-border)",
|
|
11340
|
+
borderRadius: "var(--iris-radius-md, 6px)",
|
|
11341
|
+
boxShadow: "var(--iris-shadow-lg)",
|
|
11342
|
+
padding: "var(--iris-space-sm, 12px)",
|
|
11343
|
+
minWidth: "180px",
|
|
11344
|
+
display: "flex",
|
|
11345
|
+
flexDirection: "column",
|
|
11346
|
+
gap: "var(--iris-space-xxs, 4px)"
|
|
11347
|
+
}
|
|
11348
|
+
},
|
|
11349
|
+
[
|
|
11350
|
+
...options.map(
|
|
11351
|
+
(opt) => vue.h(
|
|
11352
|
+
"div",
|
|
11353
|
+
{
|
|
11354
|
+
key: opt.value,
|
|
11355
|
+
"data-iris-filter-option": opt.value,
|
|
11356
|
+
style: { display: "flex", alignItems: "center" }
|
|
11357
|
+
},
|
|
11358
|
+
[
|
|
11359
|
+
vue.h(
|
|
11360
|
+
IrisCheckbox,
|
|
11361
|
+
{
|
|
11362
|
+
modelValue: ctx.filterDraft.value.includes(opt.value),
|
|
11363
|
+
size: "sm",
|
|
11364
|
+
"onUpdate:modelValue": () => ctx.toggle(opt.value)
|
|
11365
|
+
},
|
|
11366
|
+
{ default: () => opt.label }
|
|
11367
|
+
)
|
|
11368
|
+
]
|
|
11369
|
+
)
|
|
11370
|
+
),
|
|
11371
|
+
vue.h(
|
|
11372
|
+
"div",
|
|
11373
|
+
{
|
|
11374
|
+
style: {
|
|
11375
|
+
display: "flex",
|
|
11376
|
+
justifyContent: "flex-end",
|
|
11377
|
+
gap: "var(--iris-space-xs, 8px)",
|
|
11378
|
+
marginTop: "var(--iris-space-xs, 8px)"
|
|
11379
|
+
}
|
|
11380
|
+
},
|
|
11381
|
+
[
|
|
11382
|
+
vue.h(
|
|
11383
|
+
"button",
|
|
11384
|
+
{
|
|
11385
|
+
type: "button",
|
|
11386
|
+
"data-iris-filter-clear": "",
|
|
11387
|
+
onClick: () => {
|
|
11388
|
+
ctx.clear(st.colKey);
|
|
11389
|
+
ctx.close();
|
|
11390
|
+
},
|
|
11391
|
+
style: {
|
|
11392
|
+
border: "1px solid var(--iris-border)",
|
|
11393
|
+
background: "transparent",
|
|
11394
|
+
color: "var(--iris-foreground)",
|
|
11395
|
+
cursor: "pointer",
|
|
11396
|
+
font: "inherit",
|
|
11397
|
+
fontSize: "var(--iris-font-size-sm, 13px)",
|
|
11398
|
+
padding: "var(--iris-space-xxs, 4px) var(--iris-space-sm, 12px)",
|
|
11399
|
+
borderRadius: "var(--iris-radius-sm, 4px)"
|
|
11400
|
+
}
|
|
11401
|
+
},
|
|
11402
|
+
ctx.t("table.filterClear")
|
|
11403
|
+
),
|
|
11404
|
+
vue.h(
|
|
11405
|
+
"button",
|
|
11406
|
+
{
|
|
11407
|
+
type: "button",
|
|
11408
|
+
"data-iris-filter-confirm": "",
|
|
11409
|
+
onClick: () => {
|
|
11410
|
+
ctx.apply(st.colKey, ctx.filterDraft.value);
|
|
11411
|
+
ctx.close();
|
|
11412
|
+
},
|
|
11413
|
+
style: {
|
|
11414
|
+
border: "1px solid var(--iris-primary)",
|
|
11415
|
+
background: "var(--iris-primary)",
|
|
11416
|
+
color: "var(--iris-primary-foreground, #fff)",
|
|
11417
|
+
cursor: "pointer",
|
|
11418
|
+
font: "inherit",
|
|
11419
|
+
fontSize: "var(--iris-font-size-sm, 13px)",
|
|
11420
|
+
padding: "var(--iris-space-xxs, 4px) var(--iris-space-sm, 12px)",
|
|
11421
|
+
borderRadius: "var(--iris-radius-sm, 4px)"
|
|
11422
|
+
}
|
|
11423
|
+
},
|
|
11424
|
+
ctx.t("table.filterConfirm")
|
|
11425
|
+
)
|
|
11426
|
+
]
|
|
11427
|
+
)
|
|
11428
|
+
]
|
|
11429
|
+
);
|
|
11430
|
+
return vue.h(vue.Teleport, { to: "body" }, [node]);
|
|
11431
|
+
}
|
|
11432
|
+
function renderImportPreviewSection(ctx) {
|
|
11433
|
+
if (!ctx.rows) return null;
|
|
11434
|
+
const columns = core.previewColumnsFromRows(ctx.rows);
|
|
11435
|
+
const cellStyle = {
|
|
11436
|
+
border: "1px solid var(--iris-border)",
|
|
11437
|
+
padding: "var(--iris-space-xxs, 4px) var(--iris-space-xs, 8px)",
|
|
11438
|
+
whiteSpace: "nowrap"
|
|
11439
|
+
};
|
|
11440
|
+
const table = columns.length ? vue.h(
|
|
11441
|
+
"table",
|
|
11442
|
+
{
|
|
11443
|
+
"data-iris-import-preview-table": "",
|
|
11444
|
+
style: { borderCollapse: "collapse", fontSize: "var(--iris-font-size-sm, 13px)" }
|
|
11445
|
+
},
|
|
11446
|
+
[
|
|
11447
|
+
vue.h("thead", [
|
|
11448
|
+
vue.h(
|
|
11449
|
+
"tr",
|
|
11450
|
+
columns.map(
|
|
11451
|
+
(column) => vue.h(
|
|
11452
|
+
"th",
|
|
11453
|
+
{
|
|
11454
|
+
key: column,
|
|
11455
|
+
"data-iris-import-preview-header": column,
|
|
11456
|
+
style: {
|
|
11457
|
+
...cellStyle,
|
|
11458
|
+
background: "var(--iris-surface)",
|
|
11459
|
+
color: "var(--iris-foreground)",
|
|
11460
|
+
textAlign: "start",
|
|
11461
|
+
fontWeight: 600
|
|
11462
|
+
}
|
|
11463
|
+
},
|
|
11464
|
+
column
|
|
11465
|
+
)
|
|
11466
|
+
)
|
|
11467
|
+
)
|
|
11468
|
+
]),
|
|
11469
|
+
vue.h(
|
|
11470
|
+
"tbody",
|
|
11471
|
+
ctx.rows.slice(0, 5).map(
|
|
11472
|
+
(row, rowIndex) => vue.h(
|
|
11473
|
+
"tr",
|
|
11474
|
+
{ key: rowIndex },
|
|
11475
|
+
columns.map(
|
|
11476
|
+
(column) => vue.h(
|
|
11477
|
+
"td",
|
|
11478
|
+
{
|
|
11479
|
+
key: column,
|
|
11480
|
+
"data-iris-import-preview-cell": `${rowIndex}:${column}`,
|
|
11481
|
+
style: { ...cellStyle, color: "var(--iris-foreground)" }
|
|
11482
|
+
},
|
|
11483
|
+
String(row[column] ?? "")
|
|
11484
|
+
)
|
|
11485
|
+
)
|
|
11486
|
+
)
|
|
11487
|
+
)
|
|
11488
|
+
)
|
|
11489
|
+
]
|
|
11490
|
+
) : null;
|
|
11491
|
+
const node = vue.h(
|
|
11492
|
+
"div",
|
|
11493
|
+
{
|
|
11494
|
+
"data-iris-import-preview-backdrop": "",
|
|
11495
|
+
onPointerdown: (event) => {
|
|
11496
|
+
if (event.target === event.currentTarget) ctx.onCancel();
|
|
11497
|
+
},
|
|
11498
|
+
style: {
|
|
11499
|
+
position: "fixed",
|
|
11500
|
+
inset: 0,
|
|
11501
|
+
background: "var(--iris-backdrop, rgba(0, 0, 0, 0.5))",
|
|
11502
|
+
zIndex: "var(--iris-z-modal, 1200)",
|
|
11503
|
+
display: "flex",
|
|
11504
|
+
alignItems: "center",
|
|
11505
|
+
justifyContent: "center",
|
|
11506
|
+
padding: "var(--iris-space-lg, 24px)"
|
|
11507
|
+
}
|
|
11508
|
+
},
|
|
11509
|
+
[
|
|
11510
|
+
vue.h(
|
|
11511
|
+
"div",
|
|
11512
|
+
{
|
|
11513
|
+
"data-iris-import-preview": "",
|
|
11514
|
+
role: "dialog",
|
|
11515
|
+
"aria-modal": "true",
|
|
11516
|
+
"aria-label": ctx.t("table.importPreview.title"),
|
|
11517
|
+
style: {
|
|
11518
|
+
background: "var(--iris-surface-floating, var(--iris-surface))",
|
|
11519
|
+
color: "var(--iris-foreground)",
|
|
11520
|
+
border: "1px solid var(--iris-border)",
|
|
11521
|
+
borderRadius: "var(--iris-radius-lg, 8px)",
|
|
11522
|
+
boxShadow: "var(--iris-shadow-xl)",
|
|
11523
|
+
padding: "var(--iris-space-lg, 24px)",
|
|
11524
|
+
maxWidth: "90vw",
|
|
11525
|
+
maxHeight: "85vh",
|
|
11526
|
+
overflow: "auto",
|
|
11527
|
+
display: "flex",
|
|
11528
|
+
flexDirection: "column",
|
|
11529
|
+
gap: "var(--iris-space-sm, 12px)",
|
|
11530
|
+
fontSize: "var(--iris-font-size-md, 14px)"
|
|
11531
|
+
}
|
|
11532
|
+
},
|
|
11533
|
+
[
|
|
11534
|
+
vue.h("div", { style: { fontWeight: 600 } }, ctx.t("table.importPreview.title")),
|
|
11535
|
+
table,
|
|
11536
|
+
ctx.rows.length > 5 ? vue.h(
|
|
11537
|
+
"div",
|
|
11538
|
+
{
|
|
11539
|
+
"data-iris-import-preview-total": "",
|
|
11540
|
+
style: { color: "var(--iris-muted)", fontSize: "var(--iris-font-size-xs, 12px)" }
|
|
11541
|
+
},
|
|
11542
|
+
ctx.t("table.total", { total: ctx.rows.length })
|
|
11543
|
+
) : null,
|
|
11544
|
+
vue.h(
|
|
11545
|
+
"div",
|
|
11546
|
+
{
|
|
11547
|
+
style: {
|
|
11548
|
+
display: "flex",
|
|
11549
|
+
justifyContent: "flex-end",
|
|
11550
|
+
gap: "var(--iris-space-xs, 8px)"
|
|
11551
|
+
}
|
|
11552
|
+
},
|
|
11553
|
+
[
|
|
11554
|
+
vue.h(
|
|
11555
|
+
"button",
|
|
11556
|
+
{
|
|
11557
|
+
type: "button",
|
|
11558
|
+
"data-iris-import-preview-cancel": "",
|
|
11559
|
+
onClick: ctx.onCancel,
|
|
11560
|
+
style: {
|
|
11561
|
+
border: "1px solid var(--iris-border)",
|
|
11562
|
+
cursor: "pointer",
|
|
11563
|
+
background: "var(--iris-surface)",
|
|
11564
|
+
color: "var(--iris-foreground)",
|
|
11565
|
+
fontSize: "var(--iris-font-size-sm, 13px)",
|
|
11566
|
+
padding: "var(--iris-space-xxs, 4px) var(--iris-space-xs, 8px)",
|
|
11567
|
+
borderRadius: "var(--iris-radius-sm, 4px)"
|
|
11568
|
+
}
|
|
11569
|
+
},
|
|
11570
|
+
ctx.t("table.importPreview.cancel")
|
|
11571
|
+
),
|
|
11572
|
+
vue.h(
|
|
11573
|
+
"button",
|
|
11574
|
+
{
|
|
11575
|
+
type: "button",
|
|
11576
|
+
"data-iris-import-preview-confirm": "",
|
|
11577
|
+
onClick: ctx.onConfirm,
|
|
11578
|
+
style: {
|
|
11579
|
+
border: "none",
|
|
11580
|
+
cursor: "pointer",
|
|
11581
|
+
background: "var(--iris-primary)",
|
|
11582
|
+
color: "var(--iris-primary-foreground)",
|
|
11583
|
+
fontSize: "var(--iris-font-size-sm, 13px)",
|
|
11584
|
+
padding: "var(--iris-space-xxs, 4px) var(--iris-space-xs, 8px)",
|
|
11585
|
+
borderRadius: "var(--iris-radius-sm, 4px)"
|
|
11586
|
+
}
|
|
11587
|
+
},
|
|
11588
|
+
ctx.t("table.importPreview.confirm")
|
|
11589
|
+
)
|
|
11590
|
+
]
|
|
11591
|
+
)
|
|
11592
|
+
]
|
|
11593
|
+
)
|
|
11594
|
+
]
|
|
11595
|
+
);
|
|
11596
|
+
return vue.h(vue.Teleport, { to: "body" }, [node]);
|
|
11597
|
+
}
|
|
11598
|
+
function renderTableSummaryRow(ctx) {
|
|
11599
|
+
if (ctx.bodyData.length === 0 || !ctx.leafColumns.some((column) => column.summary)) return null;
|
|
11600
|
+
const summaryCells = [...ctx.leadingCells];
|
|
11601
|
+
for (let columnIndex = 0; columnIndex < ctx.leafColumns.length; columnIndex += 1) {
|
|
11602
|
+
const column = ctx.leafColumns[columnIndex];
|
|
11603
|
+
if (ctx.visibleColSet && !ctx.visibleColSet.has(columnIndex)) continue;
|
|
11604
|
+
const align = column.align ?? "left";
|
|
11605
|
+
const operation = column.summary;
|
|
11606
|
+
const value = operation ? core.aggregate(ctx.bodyData, (row) => ctx.getCellValue(row, column), operation) : null;
|
|
11607
|
+
const content = operation != null && value != null ? column.renderSummary ? column.renderSummary(value, ctx.bodyData) : String(value) : "";
|
|
11608
|
+
summaryCells.push(
|
|
11609
|
+
vue.h(
|
|
11610
|
+
"div",
|
|
11611
|
+
{
|
|
11612
|
+
key: column.key,
|
|
11613
|
+
role: "cell",
|
|
11614
|
+
"data-iris-table-cell": column.key,
|
|
11615
|
+
"data-iris-table-summary-cell": operation ? "" : void 0,
|
|
11616
|
+
"data-iris-table-pinned": column.pinned,
|
|
11617
|
+
style: {
|
|
11618
|
+
display: "flex",
|
|
11619
|
+
alignItems: "center",
|
|
11620
|
+
justifyContent: align === "right" ? "flex-end" : align === "center" ? "center" : "flex-start",
|
|
11621
|
+
padding: "var(--iris-space-xs, 8px) var(--iris-padding-md)",
|
|
11622
|
+
fontSize: "var(--iris-font-size-md, 14px)",
|
|
11623
|
+
whiteSpace: "nowrap",
|
|
11624
|
+
overflow: "hidden",
|
|
11625
|
+
textOverflow: "ellipsis",
|
|
11626
|
+
...ctx.visibleColSet ? { gridColumnStart: String(ctx.colTrack(columnIndex)) } : {},
|
|
11627
|
+
...ctx.pinnedStyle(column.key)
|
|
11628
|
+
}
|
|
11629
|
+
},
|
|
11630
|
+
content
|
|
11631
|
+
)
|
|
11632
|
+
);
|
|
11633
|
+
}
|
|
11634
|
+
return vue.h(
|
|
11635
|
+
"div",
|
|
11636
|
+
{
|
|
11637
|
+
role: "row",
|
|
11638
|
+
"data-iris-table-row": "summary",
|
|
11639
|
+
style: {
|
|
11640
|
+
display: "grid",
|
|
11641
|
+
gridTemplateColumns: ctx.gridTemplate,
|
|
11642
|
+
fontWeight: "600",
|
|
11643
|
+
borderTop: "2px solid var(--iris-border)",
|
|
11644
|
+
background: "var(--iris-surface)"
|
|
11645
|
+
}
|
|
11646
|
+
},
|
|
11647
|
+
summaryCells
|
|
11648
|
+
);
|
|
11649
|
+
}
|
|
11650
|
+
function renderTableStateRow(ctx) {
|
|
11651
|
+
if (ctx.error) {
|
|
11652
|
+
return vue.h("div", { role: "row", "data-iris-table-row": "error", style: ctx.stateRowStyle }, [
|
|
11653
|
+
vue.h(
|
|
11654
|
+
"span",
|
|
11655
|
+
{ style: { marginInlineEnd: ctx.onRetry ? "var(--iris-space-sm, 12px)" : "0px" } },
|
|
11656
|
+
ctx.errorContent ?? ""
|
|
11657
|
+
),
|
|
11658
|
+
ctx.retry ? vue.h(
|
|
11659
|
+
"button",
|
|
11660
|
+
{
|
|
11661
|
+
type: "button",
|
|
11662
|
+
"data-iris-table-retry": "",
|
|
11663
|
+
onClick: ctx.retry,
|
|
11664
|
+
style: {
|
|
11665
|
+
border: "1px solid var(--iris-border)",
|
|
11666
|
+
background: "var(--iris-surface)",
|
|
11667
|
+
color: "var(--iris-foreground)",
|
|
11668
|
+
borderRadius: "var(--iris-radius-sm, 4px)",
|
|
11669
|
+
padding: "var(--iris-space-xxs, 4px) var(--iris-space-xs, 8px)",
|
|
11670
|
+
fontSize: "var(--iris-font-size-sm, 13px)",
|
|
11671
|
+
cursor: "pointer"
|
|
11672
|
+
}
|
|
11673
|
+
},
|
|
11674
|
+
ctx.retryLabel
|
|
11675
|
+
) : null
|
|
11676
|
+
]);
|
|
11677
|
+
}
|
|
11678
|
+
if (ctx.loading) {
|
|
11679
|
+
return vue.h(
|
|
11680
|
+
"div",
|
|
11681
|
+
{
|
|
11682
|
+
role: "row",
|
|
11683
|
+
"aria-busy": "true",
|
|
11684
|
+
"data-iris-table-row": "loading",
|
|
11685
|
+
style: ctx.stateRowStyle
|
|
11686
|
+
},
|
|
11687
|
+
ctx.loadingContent ?? ""
|
|
11688
|
+
);
|
|
11689
|
+
}
|
|
11690
|
+
if (ctx.rowCount === 0) {
|
|
11691
|
+
return vue.h(
|
|
11692
|
+
"div",
|
|
11693
|
+
{ role: "row", "data-iris-table-row": "empty", style: ctx.stateRowStyle },
|
|
11694
|
+
ctx.emptyContent ?? ""
|
|
11695
|
+
);
|
|
11696
|
+
}
|
|
11697
|
+
return null;
|
|
11698
|
+
}
|
|
11699
|
+
function createTableKeyboard(options) {
|
|
11700
|
+
const gridKeys = /* @__PURE__ */ new Set([
|
|
11701
|
+
"ArrowUp",
|
|
11702
|
+
"ArrowDown",
|
|
11703
|
+
"ArrowLeft",
|
|
11704
|
+
"ArrowRight",
|
|
11705
|
+
"Home",
|
|
11706
|
+
"End",
|
|
11707
|
+
"PageUp",
|
|
11708
|
+
"PageDown"
|
|
11709
|
+
]);
|
|
11710
|
+
const handleGridKey = (event) => {
|
|
11711
|
+
if (!options.keyboardNavigation() || !gridKeys.has(event.key)) return;
|
|
11712
|
+
const target = event.target;
|
|
11713
|
+
if (target.dataset.gridRow === void 0) return;
|
|
11714
|
+
event.preventDefault();
|
|
11715
|
+
const next = core.nextGridCell(
|
|
11716
|
+
options.focused.value ?? { row: 0, col: 0 },
|
|
11717
|
+
event.key,
|
|
11718
|
+
{ rowCount: options.rows().length, colCount: options.columns().length, pageSize: 10 }
|
|
11719
|
+
);
|
|
11720
|
+
options.focused.value = next;
|
|
11721
|
+
options.root()?.querySelector(`[data-grid-row="${next.row}"][data-grid-col="${next.col}"]`)?.focus();
|
|
11722
|
+
};
|
|
11723
|
+
const handleCellRangeKey = (event) => {
|
|
11724
|
+
if (!options.cellRange()) return;
|
|
11725
|
+
if (event.key === "Escape") {
|
|
11726
|
+
options.range.clearRange();
|
|
11727
|
+
return;
|
|
11728
|
+
}
|
|
11729
|
+
const arrows = /* @__PURE__ */ new Set(["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"]);
|
|
11730
|
+
if (!event.shiftKey || !arrows.has(event.key)) return;
|
|
11731
|
+
const target = event.target;
|
|
11732
|
+
const row = target.dataset.irisCellRow;
|
|
11733
|
+
const col = target.dataset.irisCellCol;
|
|
11734
|
+
if (row === void 0 || col === void 0) return;
|
|
11735
|
+
event.preventDefault();
|
|
11736
|
+
const current = options.range.getState().active ?? { row: Number(row), col: Number(col) };
|
|
11737
|
+
const nextRow = event.key === "ArrowUp" ? Math.max(0, current.row - 1) : event.key === "ArrowDown" ? Math.min(options.rows().length - 1, current.row + 1) : current.row;
|
|
11738
|
+
const nextCol = event.key === "ArrowLeft" ? Math.max(0, current.col - 1) : event.key === "ArrowRight" ? Math.min(options.columns().length - 1, current.col + 1) : current.col;
|
|
11739
|
+
options.range.extendRange(nextRow, nextCol);
|
|
11740
|
+
};
|
|
11741
|
+
const isInRange = (row, col) => {
|
|
11742
|
+
const { anchor, active } = options.rangeState.value;
|
|
11743
|
+
return Boolean(
|
|
11744
|
+
anchor && active && row >= Math.min(anchor.row, active.row) && row <= Math.max(anchor.row, active.row) && col >= Math.min(anchor.col, active.col) && col <= Math.max(anchor.col, active.col)
|
|
11745
|
+
);
|
|
11746
|
+
};
|
|
11747
|
+
const activeCellRange = () => {
|
|
11748
|
+
const { anchor, active } = options.rangeState.value;
|
|
11749
|
+
if (!anchor || !active) return null;
|
|
11750
|
+
return {
|
|
11751
|
+
start: { row: Math.min(anchor.row, active.row), col: Math.min(anchor.col, active.col) },
|
|
11752
|
+
end: { row: Math.max(anchor.row, active.row), col: Math.max(anchor.col, active.col) }
|
|
11753
|
+
};
|
|
11754
|
+
};
|
|
11755
|
+
const copyActiveRange = () => {
|
|
11756
|
+
const range = activeCellRange();
|
|
11757
|
+
const clip = options.clipConfig();
|
|
11758
|
+
if (!range || clip?.copy === false) return;
|
|
11759
|
+
void core.writeClipboardText(
|
|
11760
|
+
core.serializeTableRange(
|
|
11761
|
+
options.rows(),
|
|
11762
|
+
options.columns(),
|
|
11763
|
+
range,
|
|
11764
|
+
clip?.copyFormat,
|
|
11765
|
+
clip?.copyWithFormat === true
|
|
11766
|
+
)
|
|
11767
|
+
);
|
|
11768
|
+
};
|
|
11769
|
+
const handleClipboardKey = (event) => {
|
|
11770
|
+
const clip = options.clipConfig();
|
|
11771
|
+
if (!options.cellRange() || !clip || event.defaultPrevented) return;
|
|
11772
|
+
if (event.key.toLowerCase() !== "c" || !event.ctrlKey && !event.metaKey) return;
|
|
11773
|
+
if (clip.copy === false || !activeCellRange()) return;
|
|
11774
|
+
event.preventDefault();
|
|
11775
|
+
copyActiveRange();
|
|
11776
|
+
};
|
|
11777
|
+
return {
|
|
11778
|
+
handleRootKeyDown: (event) => {
|
|
11779
|
+
handleGridKey(event);
|
|
11780
|
+
handleCellRangeKey(event);
|
|
11781
|
+
handleClipboardKey(event);
|
|
11782
|
+
},
|
|
11783
|
+
isInRange,
|
|
11784
|
+
activeCellRange,
|
|
11785
|
+
copyActiveRange
|
|
11786
|
+
};
|
|
11787
|
+
}
|
|
11788
|
+
function computeResponsiveTableColumns(columns, containerWidth, leadingWidth, widthOf) {
|
|
11789
|
+
if (containerWidth <= 0 || containerWidth >= core.RESPONSIVE_NARROW_WIDTH) {
|
|
11790
|
+
return { columns, overflow: false };
|
|
11791
|
+
}
|
|
11792
|
+
const isPinned = (column) => column.children && column.children.length > 0 ? column.children.some(isPinned) : column.pinned !== void 0;
|
|
11793
|
+
const fitted = core.computeResponsiveColumns(columns, Math.max(1, containerWidth - leadingWidth), {
|
|
11794
|
+
widthOf: (column) => widthOf(column),
|
|
11795
|
+
isPinned: (column) => isPinned(column),
|
|
11796
|
+
narrowWidth: core.RESPONSIVE_NARROW_WIDTH - leadingWidth
|
|
11797
|
+
});
|
|
11798
|
+
const natural = fitted.reduce(
|
|
11799
|
+
(sum, column) => sum + (column.children && column.children.length > 0 ? core.flattenLeafColumns([column]).reduce((nested, leaf) => nested + widthOf(leaf), 0) : widthOf(column)),
|
|
11800
|
+
leadingWidth
|
|
11801
|
+
);
|
|
11802
|
+
return { columns: fitted, overflow: natural > containerWidth };
|
|
11803
|
+
}
|
|
11804
|
+
|
|
11805
|
+
// src/primitives/table/table-styles.ts
|
|
11806
|
+
var TABLE_STYLE_ID = "iris-table-row-styles";
|
|
11807
|
+
var TABLE_STYLES = `
|
|
11808
|
+
[data-iris-table] [role="row"]:hover {
|
|
11809
|
+
--iris-cell-bg: var(--iris-surface-hover);
|
|
11810
|
+
}
|
|
11811
|
+
[data-iris-table-row-selected="true"] {
|
|
11812
|
+
--iris-cell-bg: var(--iris-surface-selected);
|
|
11813
|
+
}
|
|
11814
|
+
@media print { [data-iris-table-tabs], [data-iris-table-toolbar], [data-iris-table-form], [data-iris-scroll-hint] { display: none !important; } [data-iris-table][data-printable="true"] { border: none !important; box-shadow: var(--iris-shadow-none, none) !important; } }
|
|
11815
|
+
[data-iris-table][data-density="compact"] [data-iris-table-cell],
|
|
11816
|
+
[data-iris-table][data-density="compact"] [data-iris-table-header],
|
|
11817
|
+
[data-iris-table][data-density="compact"] [data-iris-table-summary-cell],
|
|
11818
|
+
[data-iris-table][data-density="compact"] [data-iris-table-footer-cell] { padding-block: 6px !important; }
|
|
11819
|
+
[data-iris-table][data-density="cozy"] [data-iris-table-cell],
|
|
11820
|
+
[data-iris-table][data-density="cozy"] [data-iris-table-header],
|
|
11821
|
+
[data-iris-table][data-density="cozy"] [data-iris-table-summary-cell],
|
|
11822
|
+
[data-iris-table][data-density="cozy"] [data-iris-table-footer-cell] { padding-block: 4px !important; }
|
|
11823
|
+
[data-iris-row-target="true"] {
|
|
11824
|
+
--iris-cell-bg: color-mix(in srgb, var(--iris-primary) 18%, var(--iris-background));
|
|
11825
|
+
background: color-mix(in srgb, var(--iris-primary) 18%, var(--iris-background));
|
|
11826
|
+
}
|
|
11827
|
+
`;
|
|
11828
|
+
function ensureTableStyles() {
|
|
11829
|
+
if (typeof document === "undefined" || document.getElementById(TABLE_STYLE_ID)) return;
|
|
11830
|
+
const style = document.createElement("style");
|
|
11831
|
+
style.id = TABLE_STYLE_ID;
|
|
11832
|
+
style.textContent = TABLE_STYLES;
|
|
11833
|
+
document.head.appendChild(style);
|
|
11834
|
+
}
|
|
11835
|
+
|
|
11836
|
+
// src/primitives/table/table-columns.ts
|
|
11837
|
+
function applyDetectedTableTypes(columns, detectedTypes) {
|
|
11838
|
+
const apply = (column) => {
|
|
11839
|
+
const kind = detectedTypes[column.key];
|
|
11840
|
+
const next = kind ? {
|
|
11841
|
+
...column,
|
|
11842
|
+
...kind === "number" ? column.align === void 0 ? { align: "right" } : null : column.align === void 0 ? { align: "left" } : null
|
|
11843
|
+
} : column;
|
|
11844
|
+
return next.children && next.children.length > 0 ? { ...next, children: next.children.map(apply) } : next;
|
|
11845
|
+
};
|
|
11846
|
+
return columns.map(apply);
|
|
11847
|
+
}
|
|
11848
|
+
function renderTableFilterTrigger(options) {
|
|
11849
|
+
const { column, leaf, active, open, label, onOpen } = options;
|
|
11850
|
+
if (!leaf || !column.filterable) return null;
|
|
11851
|
+
return vue.h(
|
|
11852
|
+
"button",
|
|
11853
|
+
{
|
|
11854
|
+
type: "button",
|
|
11855
|
+
"data-iris-filter-trigger": column.key,
|
|
11856
|
+
"aria-label": label,
|
|
11857
|
+
"aria-haspopup": "true",
|
|
11858
|
+
"aria-expanded": open ? "true" : void 0,
|
|
11859
|
+
"data-iris-filter-active": active ? "true" : void 0,
|
|
11860
|
+
onClick: (event) => onOpen(event, column.key),
|
|
11861
|
+
onKeydown: (event) => event.stopPropagation(),
|
|
11862
|
+
style: {
|
|
11863
|
+
border: "none",
|
|
11864
|
+
background: "transparent",
|
|
11865
|
+
cursor: "pointer",
|
|
11866
|
+
padding: "0",
|
|
11867
|
+
marginInlineStart: "var(--iris-space-xxs, 4px)",
|
|
11868
|
+
fontSize: "var(--iris-font-size-xs, 12px)",
|
|
11869
|
+
lineHeight: "1",
|
|
11870
|
+
color: active ? "var(--iris-primary)" : "var(--iris-muted)"
|
|
11871
|
+
}
|
|
11872
|
+
},
|
|
11873
|
+
"\u23F7"
|
|
11874
|
+
);
|
|
11875
|
+
}
|
|
11876
|
+
function renderTableSortIndicator(column, options) {
|
|
11877
|
+
if (!column.sortable) return null;
|
|
11878
|
+
const state = options.multiSort ? options.multiSortState.find((item) => item.key === column.key) ?? null : options.sort;
|
|
11879
|
+
const isActive = state?.key === column.key;
|
|
11880
|
+
const direction = isActive ? state.direction : null;
|
|
11881
|
+
const color = isActive ? "var(--iris-primary)" : "var(--iris-muted)";
|
|
11882
|
+
return vue.h(
|
|
11883
|
+
"span",
|
|
11884
|
+
{
|
|
11885
|
+
"aria-hidden": "true",
|
|
11886
|
+
style: {
|
|
11887
|
+
display: "inline-flex",
|
|
11888
|
+
flexDirection: "column",
|
|
11889
|
+
marginInlineStart: "var(--iris-space-xxs, 4px)",
|
|
11890
|
+
lineHeight: "0.6",
|
|
11891
|
+
fontSize: "var(--iris-font-size-xs, 12px)",
|
|
11892
|
+
color
|
|
11893
|
+
}
|
|
11894
|
+
},
|
|
11895
|
+
[
|
|
11896
|
+
vue.h("span", { style: { opacity: direction === "asc" ? "1" : "0.45" } }, "\u25B2"),
|
|
11897
|
+
vue.h("span", { style: { opacity: direction === "desc" ? "1" : "0.45" } }, "\u25BC")
|
|
11898
|
+
]
|
|
11899
|
+
);
|
|
11900
|
+
}
|
|
11901
|
+
|
|
11902
|
+
// src/primitives/table/table-row-target.ts
|
|
11903
|
+
function createTableRowTarget(root) {
|
|
11904
|
+
let timer = null;
|
|
11905
|
+
const find = (key) => {
|
|
11906
|
+
const element = root();
|
|
11907
|
+
if (!element) return null;
|
|
11908
|
+
const keyString = String(key);
|
|
11909
|
+
return Array.from(element.querySelectorAll("[data-iris-table-row-key]")).find(
|
|
11910
|
+
(node) => node.getAttribute("data-iris-table-row-key") === keyString
|
|
11911
|
+
) ?? null;
|
|
11912
|
+
};
|
|
11913
|
+
const scrollTo = (key) => {
|
|
11914
|
+
find(key)?.scrollIntoView?.({ block: "nearest" });
|
|
11915
|
+
};
|
|
11916
|
+
const goTo = (key) => {
|
|
11917
|
+
const row = find(key);
|
|
11918
|
+
if (!row) return;
|
|
11919
|
+
row.scrollIntoView?.({ block: "nearest" });
|
|
11920
|
+
root()?.querySelector('[data-iris-row-target="true"]')?.removeAttribute("data-iris-row-target");
|
|
11921
|
+
row.setAttribute("data-iris-row-target", "true");
|
|
11922
|
+
if (timer !== null) clearTimeout(timer);
|
|
11923
|
+
timer = setTimeout(() => {
|
|
11924
|
+
timer = null;
|
|
11925
|
+
row.removeAttribute("data-iris-row-target");
|
|
11926
|
+
}, 2e3);
|
|
11927
|
+
};
|
|
11928
|
+
const dispose = () => {
|
|
11929
|
+
if (timer !== null) clearTimeout(timer);
|
|
11930
|
+
timer = null;
|
|
11931
|
+
};
|
|
11932
|
+
return { find, scrollTo, goTo, dispose };
|
|
11933
|
+
}
|
|
11934
|
+
function createTablePinnedDrag(options) {
|
|
11935
|
+
const firstRightPinnedIndex = vue.computed(() => {
|
|
11936
|
+
const index = options.columns().findIndex((column) => column.pinned === "right");
|
|
11937
|
+
return index < 0 ? options.columns().length : index;
|
|
11938
|
+
});
|
|
11939
|
+
const pinnedBoundaryColumn = vue.computed(() => {
|
|
11940
|
+
if (!options.enabled()) return null;
|
|
11941
|
+
for (let index = firstRightPinnedIndex.value - 1; index >= 0; index -= 1) {
|
|
11942
|
+
const column = options.columns()[index];
|
|
11943
|
+
if (column?.pinned === "left") return column;
|
|
11944
|
+
}
|
|
11945
|
+
return null;
|
|
11946
|
+
});
|
|
11947
|
+
const handleRefs = /* @__PURE__ */ new Map();
|
|
11948
|
+
const wiredKeys = /* @__PURE__ */ new Set();
|
|
11949
|
+
const activeKey = vue.ref(null);
|
|
11950
|
+
const dragDx = vue.ref(0);
|
|
11951
|
+
const getHandleRef = (key) => {
|
|
11952
|
+
let handle = handleRefs.get(key);
|
|
11953
|
+
if (!handle) {
|
|
11954
|
+
handle = vue.ref(null);
|
|
11955
|
+
handleRefs.set(key, handle);
|
|
11956
|
+
}
|
|
11957
|
+
return handle;
|
|
11958
|
+
};
|
|
11959
|
+
const resolvePinnedCount = (dx) => {
|
|
11960
|
+
const columns = options.columns();
|
|
11961
|
+
const cap = firstRightPinnedIndex.value;
|
|
11962
|
+
const current = core.leftPinnedCount(columns, cap);
|
|
11963
|
+
let currentWidth = 0;
|
|
11964
|
+
for (let index = 0; index < current; index += 1) {
|
|
11965
|
+
const column = columns[index];
|
|
11966
|
+
if (column) currentWidth += options.widthOf(column);
|
|
11967
|
+
}
|
|
11968
|
+
return core.pinnedCountFromBudget(
|
|
11969
|
+
columns,
|
|
11970
|
+
(column) => options.widthOf(column),
|
|
11971
|
+
currentWidth + dx,
|
|
11972
|
+
cap
|
|
11973
|
+
);
|
|
11974
|
+
};
|
|
11975
|
+
const commitPinnedCount = (count) => {
|
|
11976
|
+
if (!options.enabled()) return;
|
|
11977
|
+
const columns = options.columns();
|
|
11978
|
+
const cap = firstRightPinnedIndex.value;
|
|
11979
|
+
const clamped = Math.max(0, Math.min(cap, count));
|
|
11980
|
+
const current = core.leftPinnedCount(columns, cap);
|
|
11981
|
+
if (clamped === current) return;
|
|
11982
|
+
for (let index = 0; index < cap; index += 1) {
|
|
11983
|
+
const column = columns[index];
|
|
11984
|
+
if (!column) continue;
|
|
11985
|
+
const target = index < clamped ? "left" : null;
|
|
11986
|
+
if (column.pinned === target) continue;
|
|
11987
|
+
options.onColumnPinnedChange?.(column.key, target);
|
|
11988
|
+
}
|
|
11989
|
+
options.onPinnedCountChange?.(clamped);
|
|
11990
|
+
};
|
|
11991
|
+
const wire = (key) => {
|
|
11992
|
+
if (wiredKeys.has(key)) return;
|
|
11993
|
+
wiredKeys.add(key);
|
|
11994
|
+
const handle = getHandleRef(key);
|
|
11995
|
+
useDrag({
|
|
11996
|
+
handle,
|
|
11997
|
+
disabled: vue.computed(() => !options.enabled()),
|
|
11998
|
+
onStart: () => {
|
|
11999
|
+
activeKey.value = key;
|
|
12000
|
+
dragDx.value = 0;
|
|
12001
|
+
},
|
|
12002
|
+
onDrag: ({ dx }) => {
|
|
12003
|
+
activeKey.value = key;
|
|
12004
|
+
dragDx.value = dx;
|
|
12005
|
+
},
|
|
12006
|
+
onEnd: ({ dx }) => {
|
|
12007
|
+
commitPinnedCount(resolvePinnedCount(dx));
|
|
12008
|
+
activeKey.value = null;
|
|
12009
|
+
dragDx.value = 0;
|
|
12010
|
+
}
|
|
12011
|
+
});
|
|
12012
|
+
};
|
|
12013
|
+
for (const column of options.columns()) wire(column.key);
|
|
12014
|
+
return (column) => {
|
|
12015
|
+
const boundary = pinnedBoundaryColumn.value;
|
|
12016
|
+
if (!options.enabled() || !boundary || boundary.key !== column.key) return null;
|
|
12017
|
+
const handle = getHandleRef(column.key);
|
|
12018
|
+
return vue.h(
|
|
12019
|
+
"span",
|
|
12020
|
+
{
|
|
12021
|
+
ref: (element) => {
|
|
12022
|
+
handle.value = element ?? null;
|
|
12023
|
+
},
|
|
12024
|
+
role: "separator",
|
|
12025
|
+
"aria-orientation": "vertical",
|
|
12026
|
+
"aria-label": `Adjust pinned column count at ${column.title}`,
|
|
12027
|
+
tabindex: 0,
|
|
12028
|
+
"data-iris-pinned-drag-handle": "",
|
|
12029
|
+
"data-column-key": column.key,
|
|
12030
|
+
"data-iris-pinned-drag-active": activeKey.value === column.key && dragDx.value !== 0 ? "true" : void 0,
|
|
12031
|
+
onPointerdown: (event) => event.stopPropagation(),
|
|
12032
|
+
onKeydown: (event) => {
|
|
12033
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
12034
|
+
event.preventDefault();
|
|
12035
|
+
event.stopPropagation();
|
|
12036
|
+
commitPinnedCount(resolvePinnedCount(0) + (event.key === "ArrowRight" ? 1 : -1));
|
|
12037
|
+
},
|
|
12038
|
+
style: {
|
|
12039
|
+
position: "absolute",
|
|
12040
|
+
top: "0",
|
|
12041
|
+
right: "0",
|
|
12042
|
+
bottom: "0",
|
|
12043
|
+
width: "8px",
|
|
12044
|
+
cursor: "col-resize",
|
|
12045
|
+
touchAction: "none",
|
|
12046
|
+
userSelect: "none",
|
|
12047
|
+
zIndex: "2",
|
|
12048
|
+
transform: activeKey.value === column.key && dragDx.value !== 0 ? `translateX(${dragDx.value}px)` : void 0
|
|
12049
|
+
}
|
|
12050
|
+
},
|
|
12051
|
+
vue.h("span", {
|
|
12052
|
+
"aria-hidden": "true",
|
|
12053
|
+
"data-iris-pinned-drag-line": "",
|
|
12054
|
+
style: {
|
|
12055
|
+
position: "absolute",
|
|
12056
|
+
top: "0",
|
|
12057
|
+
bottom: "0",
|
|
12058
|
+
insetInlineStart: "50%",
|
|
12059
|
+
width: "2px",
|
|
12060
|
+
background: "var(--iris-primary)",
|
|
12061
|
+
transform: "translateX(-50%)"
|
|
12062
|
+
}
|
|
12063
|
+
})
|
|
12064
|
+
);
|
|
12065
|
+
};
|
|
12066
|
+
}
|
|
12067
|
+
function useTableImport(isPreviewEnabled, getOnImport) {
|
|
12068
|
+
const importFileInput = vue.ref(null);
|
|
12069
|
+
const importPreviewRows = vue.ref(null);
|
|
12070
|
+
const handleImportFile = (event) => {
|
|
12071
|
+
const input = event.target;
|
|
12072
|
+
const file = input?.files?.[0];
|
|
12073
|
+
if (!file || !getOnImport() || typeof FileReader === "undefined") return;
|
|
12074
|
+
const reader = new FileReader();
|
|
12075
|
+
reader.onload = () => {
|
|
12076
|
+
const rows = core.rowsFromCsv(String(reader.result ?? ""));
|
|
12077
|
+
if (rows.length === 0) return;
|
|
12078
|
+
if (isPreviewEnabled()) importPreviewRows.value = rows;
|
|
12079
|
+
else getOnImport()?.(rows);
|
|
12080
|
+
};
|
|
12081
|
+
reader.readAsText(file);
|
|
12082
|
+
if (input) input.value = "";
|
|
12083
|
+
};
|
|
12084
|
+
const confirmImportPreview = () => {
|
|
12085
|
+
if (!importPreviewRows.value) return;
|
|
12086
|
+
getOnImport()?.(importPreviewRows.value);
|
|
12087
|
+
importPreviewRows.value = null;
|
|
12088
|
+
};
|
|
12089
|
+
const cancelImportPreview = () => {
|
|
12090
|
+
importPreviewRows.value = null;
|
|
12091
|
+
};
|
|
12092
|
+
vue.watch(importPreviewRows, (rows, _previous, onCleanup) => {
|
|
12093
|
+
if (!rows || typeof window === "undefined") return;
|
|
12094
|
+
const closeOnEscape = (event) => {
|
|
12095
|
+
if (event.key === "Escape") cancelImportPreview();
|
|
12096
|
+
};
|
|
12097
|
+
window.addEventListener("keydown", closeOnEscape);
|
|
12098
|
+
onCleanup(() => window.removeEventListener("keydown", closeOnEscape));
|
|
12099
|
+
});
|
|
12100
|
+
return {
|
|
12101
|
+
importFileInput,
|
|
12102
|
+
importPreviewRows,
|
|
12103
|
+
handleImportFile,
|
|
12104
|
+
confirmImportPreview,
|
|
12105
|
+
cancelImportPreview
|
|
12106
|
+
};
|
|
12107
|
+
}
|
|
12108
|
+
var editorInputStyle = (error) => ({
|
|
12109
|
+
width: "100%",
|
|
12110
|
+
border: `1px solid ${error ? "var(--iris-danger)" : "var(--iris-primary)"}`,
|
|
12111
|
+
borderRadius: "var(--iris-radius-sm)",
|
|
12112
|
+
padding: "var(--iris-space-xxs, 4px) var(--iris-padding-sm, 6px)",
|
|
12113
|
+
font: "inherit",
|
|
12114
|
+
background: "var(--iris-background)",
|
|
12115
|
+
color: "var(--iris-foreground)",
|
|
12116
|
+
outline: "none",
|
|
12117
|
+
boxShadow: "0 0 0 3px color-mix(in srgb, var(--iris-primary) 18%, transparent)"
|
|
12118
|
+
});
|
|
12119
|
+
function editorErrorVNode(editCellId, error) {
|
|
12120
|
+
return vue.h(
|
|
12121
|
+
"div",
|
|
12122
|
+
{
|
|
12123
|
+
id: `${editCellId}-error`,
|
|
12124
|
+
role: "alert",
|
|
12125
|
+
"data-iris-table-editor-error": "",
|
|
12126
|
+
style: {
|
|
12127
|
+
marginTop: "var(--iris-space-xxs, 4px)",
|
|
12128
|
+
fontSize: "var(--iris-font-size-xs, 12px)",
|
|
12129
|
+
color: "var(--iris-danger)"
|
|
12130
|
+
}
|
|
12131
|
+
},
|
|
12132
|
+
error
|
|
12133
|
+
);
|
|
12134
|
+
}
|
|
12135
|
+
var editPreviewStyle = {
|
|
12136
|
+
flexBasis: "100%",
|
|
12137
|
+
minWidth: "0",
|
|
12138
|
+
marginTop: "var(--iris-space-xxs, 4px)",
|
|
12139
|
+
fontSize: "var(--iris-font-size-xs, 12px)",
|
|
12140
|
+
color: "var(--iris-muted)"
|
|
12141
|
+
};
|
|
12142
|
+
function previewVNode(ctx, row, col, draft) {
|
|
12143
|
+
if (!ctx.editPreview || !col.formatter) return null;
|
|
12144
|
+
return vue.h(
|
|
12145
|
+
"div",
|
|
12146
|
+
{ "data-iris-edit-preview": "", style: editPreviewStyle },
|
|
12147
|
+
ctx.previewValue(row, col, draft)
|
|
12148
|
+
);
|
|
12149
|
+
}
|
|
12150
|
+
function renderRowSessionContent(ctx, row, col, index, key, editCellId, session) {
|
|
12151
|
+
const error = session.error;
|
|
12152
|
+
const input = vue.h("input", {
|
|
12153
|
+
ref: (el) => {
|
|
12154
|
+
ctx.rowEditorRefs.set(col.key, el ?? null);
|
|
12155
|
+
},
|
|
12156
|
+
type: col.editor === "number" ? "number" : "text",
|
|
12157
|
+
value: session.draft,
|
|
12158
|
+
"data-iris-table-editor": "",
|
|
12159
|
+
"aria-invalid": error ? "true" : void 0,
|
|
12160
|
+
"aria-describedby": error ? `${editCellId}-error` : void 0,
|
|
12161
|
+
onInput: (e) => {
|
|
12162
|
+
session.draft = e.target.value;
|
|
12163
|
+
},
|
|
12164
|
+
onKeydown: (e) => {
|
|
12165
|
+
if (e.key === "Enter") {
|
|
12166
|
+
e.preventDefault();
|
|
12167
|
+
ctx.commitRowSession(key, col, index, editCellId);
|
|
12168
|
+
} else if (e.key === "Escape") {
|
|
12169
|
+
e.preventDefault();
|
|
12170
|
+
ctx.cancelRowEdit();
|
|
12171
|
+
}
|
|
12172
|
+
},
|
|
12173
|
+
onBlur: () => ctx.commitRowSession(key, col, index, editCellId),
|
|
12174
|
+
onClick: (e) => e.stopPropagation(),
|
|
12175
|
+
onDblclick: (e) => e.stopPropagation(),
|
|
12176
|
+
style: editorInputStyle(error)
|
|
12177
|
+
});
|
|
12178
|
+
const preview = previewVNode(ctx, row, col, session.draft);
|
|
12179
|
+
const children = [input, preview, error ? editorErrorVNode(editCellId, error) : null].filter(
|
|
12180
|
+
(node) => node !== null
|
|
12181
|
+
);
|
|
12182
|
+
return children.length === 1 ? children[0] : children;
|
|
12183
|
+
}
|
|
12184
|
+
function renderCellEditContent(ctx, row, col, index, editCellId) {
|
|
12185
|
+
const error = ctx.editError.value;
|
|
12186
|
+
const input = vue.h("input", {
|
|
12187
|
+
ref: (el) => {
|
|
12188
|
+
ctx.editorInputRef.value = el ?? null;
|
|
12189
|
+
},
|
|
12190
|
+
type: col.editor === "number" ? "number" : "text",
|
|
12191
|
+
value: ctx.editingDraft.value,
|
|
12192
|
+
"data-iris-table-editor": "",
|
|
12193
|
+
"aria-invalid": error ? "true" : void 0,
|
|
12194
|
+
"aria-describedby": error ? `${editCellId}-error` : void 0,
|
|
12195
|
+
onInput: (e) => {
|
|
12196
|
+
ctx.editingDraft.value = e.target.value;
|
|
12197
|
+
},
|
|
12198
|
+
onKeydown: (e) => {
|
|
12199
|
+
if (e.key === "Enter") {
|
|
12200
|
+
e.preventDefault();
|
|
12201
|
+
ctx.commitEdit(row, col, index);
|
|
12202
|
+
} else if (e.key === "Escape") {
|
|
12203
|
+
e.preventDefault();
|
|
12204
|
+
ctx.cancelEdit();
|
|
12205
|
+
}
|
|
12206
|
+
},
|
|
12207
|
+
onBlur: () => ctx.commitEdit(row, col, index),
|
|
12208
|
+
onClick: (e) => e.stopPropagation(),
|
|
12209
|
+
onDblclick: (e) => e.stopPropagation(),
|
|
12210
|
+
style: editorInputStyle(error)
|
|
12211
|
+
});
|
|
12212
|
+
const preview = previewVNode(ctx, row, col, ctx.editingDraft.value);
|
|
12213
|
+
const children = [input, preview, error ? editorErrorVNode(editCellId, error) : null].filter(
|
|
12214
|
+
(node) => node !== null
|
|
12215
|
+
);
|
|
12216
|
+
return children.length === 1 ? children[0] : children;
|
|
12217
|
+
}
|
|
12218
|
+
function renderGroupedHeader(ctx, matrix) {
|
|
12219
|
+
const lead = (ctx.showDrag ? 1 : 0) + (ctx.showSeq ? 1 : 0) + (ctx.showDetail ? 1 : 0) + (ctx.showSelection ? 1 : 0);
|
|
12220
|
+
const cells = [];
|
|
12221
|
+
if (ctx.showDrag) {
|
|
12222
|
+
cells.push(
|
|
12223
|
+
vue.h("div", {
|
|
12224
|
+
key: "__drag__",
|
|
12225
|
+
role: "columnheader",
|
|
12226
|
+
"data-iris-table-header": "__drag",
|
|
12227
|
+
style: { gridColumn: "1", gridRow: "1 / -1" }
|
|
12228
|
+
})
|
|
12229
|
+
);
|
|
12230
|
+
}
|
|
12231
|
+
if (ctx.showSeq) {
|
|
12232
|
+
cells.push(
|
|
12233
|
+
vue.h("div", {
|
|
12234
|
+
key: "__seq__",
|
|
12235
|
+
role: "columnheader",
|
|
12236
|
+
"data-iris-table-header": "__seq",
|
|
12237
|
+
style: { gridColumn: ctx.showDrag ? "2" : "1", gridRow: "1 / -1" }
|
|
12238
|
+
})
|
|
12239
|
+
);
|
|
12240
|
+
}
|
|
12241
|
+
if (ctx.showDetail) {
|
|
12242
|
+
cells.push(
|
|
12243
|
+
vue.h("div", {
|
|
12244
|
+
key: "__expand__",
|
|
12245
|
+
role: "columnheader",
|
|
12246
|
+
style: {
|
|
12247
|
+
gridColumn: `${(ctx.showDrag ? 1 : 0) + (ctx.showSeq ? 1 : 0) + 1}`,
|
|
12248
|
+
gridRow: "1 / -1"
|
|
12249
|
+
}
|
|
12250
|
+
})
|
|
12251
|
+
);
|
|
12252
|
+
}
|
|
12253
|
+
if (ctx.showSelection) {
|
|
12254
|
+
cells.push(
|
|
12255
|
+
vue.h(
|
|
12256
|
+
"div",
|
|
12257
|
+
{
|
|
12258
|
+
key: "__select__",
|
|
12259
|
+
role: "columnheader",
|
|
12260
|
+
"data-iris-table-header": "",
|
|
12261
|
+
style: {
|
|
12262
|
+
gridColumn: `${(ctx.showDrag ? 1 : 0) + (ctx.showSeq ? 1 : 0) + (ctx.showDetail ? 1 : 0) + 1}`,
|
|
12263
|
+
gridRow: "1 / -1",
|
|
12264
|
+
display: "flex",
|
|
12265
|
+
alignItems: "center",
|
|
12266
|
+
justifyContent: "center",
|
|
12267
|
+
padding: "8px 12px",
|
|
12268
|
+
background: "var(--iris-surface)",
|
|
12269
|
+
borderBottom: "1px solid var(--iris-border)"
|
|
12270
|
+
}
|
|
12271
|
+
},
|
|
12272
|
+
ctx.selectable === "multi" ? [
|
|
12273
|
+
[
|
|
12274
|
+
vue.h(IrisCheckbox, {
|
|
12275
|
+
modelValue: ctx.allSelected.value ? true : ctx.someSelected.value ? "indeterminate" : false,
|
|
12276
|
+
size: "sm",
|
|
12277
|
+
ariaLabel: ctx.t("table.selectAll"),
|
|
12278
|
+
"onUpdate:modelValue": ctx.toggleAll
|
|
12279
|
+
}),
|
|
12280
|
+
ctx.selection && ctx.selection.length > 0 ? vue.h(
|
|
12281
|
+
"span",
|
|
12282
|
+
{
|
|
12283
|
+
"data-iris-table-selected-count": "",
|
|
12284
|
+
style: {
|
|
12285
|
+
marginInlineStart: "var(--iris-space-xs, 8px)",
|
|
12286
|
+
fontSize: "var(--iris-font-size-sm, 13px)",
|
|
12287
|
+
color: "var(--iris-muted)",
|
|
12288
|
+
whiteSpace: "nowrap"
|
|
12289
|
+
}
|
|
12290
|
+
},
|
|
12291
|
+
ctx.t("table.selectedCount", { count: String(ctx.selection.length) })
|
|
12292
|
+
) : null
|
|
12293
|
+
]
|
|
12294
|
+
] : ""
|
|
12295
|
+
)
|
|
12296
|
+
);
|
|
12297
|
+
}
|
|
12298
|
+
for (const rowCells of matrix) {
|
|
12299
|
+
for (const cell of rowCells) {
|
|
12300
|
+
const col = cell.column;
|
|
12301
|
+
const isLeaf = !col.children || col.children.length === 0;
|
|
12302
|
+
const sortable = isLeaf && col.sortable;
|
|
12303
|
+
const align = col.align ?? "left";
|
|
12304
|
+
const headerSlot = ctx.slots[`header.${col.key}`];
|
|
12305
|
+
const title = headerSlot?.({ column: col }) ?? col.title;
|
|
12306
|
+
cells.push(
|
|
12307
|
+
vue.h(
|
|
12308
|
+
"div",
|
|
12309
|
+
{
|
|
12310
|
+
key: `${col.key}-${cell.level}`,
|
|
12311
|
+
role: "columnheader",
|
|
12312
|
+
"data-iris-table-header": col.key,
|
|
12313
|
+
"data-iris-table-header-group": isLeaf ? void 0 : "",
|
|
12314
|
+
"aria-colspan": cell.colSpan,
|
|
12315
|
+
onClick: sortable ? () => ctx.onHeaderClick(col) : void 0,
|
|
12316
|
+
"aria-sort": sortable ? ctx.ariaSortFor(col) : void 0,
|
|
12317
|
+
style: {
|
|
12318
|
+
gridColumn: `${lead + cell.colStart} / span ${cell.colSpan}`,
|
|
12319
|
+
gridRow: `${cell.level + 1} / span ${cell.rowSpan}`,
|
|
12320
|
+
display: "flex",
|
|
12321
|
+
alignItems: "center",
|
|
12322
|
+
justifyContent: isLeaf ? align === "right" ? "flex-end" : align === "center" ? "center" : "flex-start" : "center",
|
|
12323
|
+
padding: "8px var(--iris-padding-md)",
|
|
12324
|
+
cursor: sortable ? "pointer" : "default",
|
|
12325
|
+
userSelect: sortable ? "none" : "auto",
|
|
12326
|
+
background: "var(--iris-surface)",
|
|
12327
|
+
borderBottom: "1px solid var(--iris-border)",
|
|
12328
|
+
fontWeight: "600",
|
|
12329
|
+
fontSize: "var(--iris-font-size-md, 14px)",
|
|
12330
|
+
color: "var(--iris-foreground)",
|
|
12331
|
+
whiteSpace: "nowrap",
|
|
12332
|
+
overflow: "hidden",
|
|
12333
|
+
textOverflow: "ellipsis"
|
|
12334
|
+
}
|
|
12335
|
+
},
|
|
12336
|
+
[
|
|
12337
|
+
title,
|
|
12338
|
+
sortable ? ctx.sortIndicator(col) : null,
|
|
12339
|
+
ctx.multiSortSeq(col),
|
|
12340
|
+
ctx.renderFilterTrigger(col, isLeaf),
|
|
12341
|
+
isLeaf ? ctx.pinnedDragHandle?.(col) ?? null : null
|
|
12342
|
+
]
|
|
12343
|
+
)
|
|
12344
|
+
);
|
|
12345
|
+
}
|
|
10545
12346
|
}
|
|
12347
|
+
return vue.h(
|
|
12348
|
+
"div",
|
|
12349
|
+
{
|
|
12350
|
+
role: "row",
|
|
12351
|
+
"data-iris-table-row": "header",
|
|
12352
|
+
"data-iris-table-header-row": "",
|
|
12353
|
+
"data-iris-table-header-grouped": "",
|
|
12354
|
+
style: {
|
|
12355
|
+
display: "grid",
|
|
12356
|
+
gridTemplateColumns: ctx.gridTemplate.value,
|
|
12357
|
+
gridTemplateRows: `repeat(${matrix.length}, auto)`
|
|
12358
|
+
}
|
|
12359
|
+
},
|
|
12360
|
+
cells
|
|
12361
|
+
);
|
|
12362
|
+
}
|
|
12363
|
+
function createTableViewsController(options) {
|
|
12364
|
+
const views = vue.ref(core.readTableViews(options.config()));
|
|
12365
|
+
const internalActiveKey = vue.ref(null);
|
|
12366
|
+
const activeKey = vue.computed(() => {
|
|
12367
|
+
const config = options.config();
|
|
12368
|
+
return config?.activeKey !== void 0 ? config.activeKey ?? null : internalActiveKey.value;
|
|
12369
|
+
});
|
|
12370
|
+
const saveOpen = vue.ref(false);
|
|
12371
|
+
const draft = vue.ref("");
|
|
12372
|
+
const activeTab = vue.ref(null);
|
|
12373
|
+
const persist = (next) => {
|
|
12374
|
+
views.value = next;
|
|
12375
|
+
core.writeTableViews(options.config(), next);
|
|
12376
|
+
};
|
|
12377
|
+
const applySnapshot = (snapshot) => {
|
|
12378
|
+
if (Object.prototype.hasOwnProperty.call(snapshot, "sort"))
|
|
12379
|
+
options.setSort(snapshot.sort ?? null);
|
|
12380
|
+
};
|
|
12381
|
+
const select = (key) => {
|
|
12382
|
+
const view = views.value.find((candidate) => candidate.name === key);
|
|
12383
|
+
if (!view) return;
|
|
12384
|
+
applySnapshot(view.snapshot);
|
|
12385
|
+
internalActiveKey.value = key;
|
|
12386
|
+
options.onActiveViewChange(key);
|
|
12387
|
+
};
|
|
12388
|
+
const save = (name) => {
|
|
12389
|
+
const trimmed = name.trim();
|
|
12390
|
+
if (!trimmed) return;
|
|
12391
|
+
const currentSort = options.sort.value;
|
|
12392
|
+
const entry = {
|
|
12393
|
+
name: trimmed,
|
|
12394
|
+
snapshot: { sort: currentSort ? { ...currentSort } : null }
|
|
12395
|
+
};
|
|
12396
|
+
const index = views.value.findIndex((view) => view.name === trimmed);
|
|
12397
|
+
persist(
|
|
12398
|
+
index < 0 ? [...views.value, entry] : views.value.map((view, i) => i === index ? entry : view)
|
|
12399
|
+
);
|
|
12400
|
+
internalActiveKey.value = trimmed;
|
|
12401
|
+
options.onActiveViewChange(trimmed);
|
|
12402
|
+
};
|
|
12403
|
+
const remove = (key) => {
|
|
12404
|
+
persist(views.value.filter((view) => view.name !== key));
|
|
12405
|
+
if (activeKey.value === key) {
|
|
12406
|
+
internalActiveKey.value = null;
|
|
12407
|
+
options.onActiveViewChange(null);
|
|
12408
|
+
}
|
|
12409
|
+
};
|
|
12410
|
+
const applyTab = (tab) => {
|
|
12411
|
+
activeTab.value = tab.key;
|
|
12412
|
+
for (const name of tab.views ?? []) select(name);
|
|
12413
|
+
};
|
|
10546
12414
|
return {
|
|
10547
|
-
|
|
10548
|
-
|
|
10549
|
-
|
|
10550
|
-
|
|
10551
|
-
|
|
12415
|
+
activeKey,
|
|
12416
|
+
views,
|
|
12417
|
+
saveOpen,
|
|
12418
|
+
draft,
|
|
12419
|
+
renderTabs: (tabs) => renderTableTabs(tabs, activeTab, applyTab),
|
|
12420
|
+
renderViews: () => renderTableViews({
|
|
12421
|
+
config: options.config(),
|
|
12422
|
+
views,
|
|
12423
|
+
activeKey,
|
|
12424
|
+
saveOpen,
|
|
12425
|
+
draft,
|
|
12426
|
+
onSelect: select,
|
|
12427
|
+
onSave: save,
|
|
12428
|
+
onDelete: remove
|
|
12429
|
+
})
|
|
10552
12430
|
};
|
|
10553
12431
|
}
|
|
10554
|
-
|
|
10555
|
-
|
|
10556
|
-
|
|
10557
|
-
|
|
10558
|
-
|
|
12432
|
+
function renderTableViews(ctx) {
|
|
12433
|
+
if (!ctx.config) return null;
|
|
12434
|
+
return vue.h(
|
|
12435
|
+
"div",
|
|
12436
|
+
{
|
|
12437
|
+
"data-iris-table-views-bar": "",
|
|
12438
|
+
style: {
|
|
12439
|
+
display: "flex",
|
|
12440
|
+
alignItems: "center",
|
|
12441
|
+
gap: "var(--iris-space-xxs, 4px)",
|
|
12442
|
+
padding: "var(--iris-space-xxs, 4px) 0"
|
|
12443
|
+
}
|
|
12444
|
+
},
|
|
12445
|
+
[
|
|
12446
|
+
vue.h(
|
|
12447
|
+
"select",
|
|
12448
|
+
{
|
|
12449
|
+
"data-iris-table-views": "",
|
|
12450
|
+
value: ctx.saveOpen.value ? core.TABLE_VIEWS_SAVE_ITEM : ctx.activeKey.value ?? "",
|
|
12451
|
+
"aria-label": "Table views",
|
|
12452
|
+
onChange: (event) => {
|
|
12453
|
+
const value = event.target.value;
|
|
12454
|
+
if (value === core.TABLE_VIEWS_SAVE_ITEM) {
|
|
12455
|
+
ctx.draft.value = "";
|
|
12456
|
+
ctx.saveOpen.value = true;
|
|
12457
|
+
} else if (value !== "") {
|
|
12458
|
+
ctx.onSelect(value);
|
|
12459
|
+
}
|
|
12460
|
+
},
|
|
12461
|
+
style: {
|
|
12462
|
+
border: "1px solid var(--iris-border)",
|
|
12463
|
+
borderRadius: "var(--iris-radius-sm, 4px)",
|
|
12464
|
+
background: "var(--iris-surface)",
|
|
12465
|
+
color: "var(--iris-foreground)",
|
|
12466
|
+
font: "inherit",
|
|
12467
|
+
fontSize: "var(--iris-font-size-sm, 13px)",
|
|
12468
|
+
padding: "0 var(--iris-space-xxs, 4px)",
|
|
12469
|
+
maxWidth: "180px"
|
|
12470
|
+
}
|
|
12471
|
+
},
|
|
12472
|
+
[
|
|
12473
|
+
ctx.activeKey.value === null && !ctx.saveOpen.value ? vue.h("option", { value: "", disabled: true }, "Select view") : null,
|
|
12474
|
+
...ctx.views.value.map(
|
|
12475
|
+
(view) => vue.h(
|
|
12476
|
+
"option",
|
|
12477
|
+
{ key: view.name, value: view.name },
|
|
12478
|
+
ctx.config?.label?.(view.name) ?? view.name
|
|
12479
|
+
)
|
|
12480
|
+
),
|
|
12481
|
+
vue.h("option", { value: core.TABLE_VIEWS_SAVE_ITEM }, "\uFF0B Save view")
|
|
12482
|
+
]
|
|
12483
|
+
),
|
|
12484
|
+
ctx.saveOpen.value ? vue.h("input", {
|
|
12485
|
+
"data-iris-views-save": "",
|
|
12486
|
+
type: "text",
|
|
12487
|
+
value: ctx.draft.value,
|
|
12488
|
+
placeholder: "View name",
|
|
12489
|
+
"aria-label": "Save view",
|
|
12490
|
+
onInput: (event) => {
|
|
12491
|
+
ctx.draft.value = event.target.value;
|
|
12492
|
+
},
|
|
12493
|
+
onKeydown: (event) => {
|
|
12494
|
+
if (event.key === "Enter") {
|
|
12495
|
+
event.preventDefault();
|
|
12496
|
+
if (ctx.draft.value.trim()) ctx.onSave(ctx.draft.value);
|
|
12497
|
+
ctx.saveOpen.value = false;
|
|
12498
|
+
} else if (event.key === "Escape") {
|
|
12499
|
+
ctx.saveOpen.value = false;
|
|
12500
|
+
}
|
|
12501
|
+
},
|
|
12502
|
+
onBlur: () => {
|
|
12503
|
+
ctx.saveOpen.value = false;
|
|
12504
|
+
},
|
|
12505
|
+
style: {
|
|
12506
|
+
border: "1px solid var(--iris-border)",
|
|
12507
|
+
borderRadius: "var(--iris-radius-sm, 4px)",
|
|
12508
|
+
padding: "var(--iris-space-xxs, 4px)",
|
|
12509
|
+
width: "120px",
|
|
12510
|
+
font: "inherit"
|
|
12511
|
+
}
|
|
12512
|
+
}) : null,
|
|
12513
|
+
ctx.activeKey.value !== null ? vue.h(
|
|
12514
|
+
"button",
|
|
12515
|
+
{
|
|
12516
|
+
type: "button",
|
|
12517
|
+
"data-iris-table-views-delete": "",
|
|
12518
|
+
"aria-label": "Delete view",
|
|
12519
|
+
onClick: () => ctx.onDelete(ctx.activeKey.value),
|
|
12520
|
+
style: {
|
|
12521
|
+
border: "none",
|
|
12522
|
+
background: "transparent",
|
|
12523
|
+
cursor: "pointer",
|
|
12524
|
+
color: "var(--iris-muted)",
|
|
12525
|
+
font: "inherit",
|
|
12526
|
+
padding: "0 var(--iris-space-xxs, 4px)"
|
|
12527
|
+
}
|
|
12528
|
+
},
|
|
12529
|
+
"\xD7"
|
|
12530
|
+
) : null
|
|
12531
|
+
]
|
|
12532
|
+
);
|
|
10559
12533
|
}
|
|
10560
|
-
|
|
10561
|
-
|
|
10562
|
-
|
|
10563
|
-
|
|
10564
|
-
|
|
10565
|
-
|
|
10566
|
-
|
|
10567
|
-
|
|
10568
|
-
|
|
10569
|
-
|
|
10570
|
-
|
|
10571
|
-
|
|
12534
|
+
function renderTableTabs(tabs, activeTab, onApply) {
|
|
12535
|
+
const unique = core.uniqueTableTabs(tabs ?? []);
|
|
12536
|
+
if (unique.length === 0) return null;
|
|
12537
|
+
return vue.h(
|
|
12538
|
+
"div",
|
|
12539
|
+
{
|
|
12540
|
+
role: "tablist",
|
|
12541
|
+
"data-iris-table-tabs": "",
|
|
12542
|
+
style: {
|
|
12543
|
+
display: "flex",
|
|
12544
|
+
alignItems: "center",
|
|
12545
|
+
gap: "var(--iris-space-xs, 8px)",
|
|
12546
|
+
padding: "var(--iris-space-xs, 8px) var(--iris-space-sm, 12px)",
|
|
12547
|
+
border: "1px solid var(--iris-border)",
|
|
12548
|
+
borderBottom: "none",
|
|
12549
|
+
borderTopLeftRadius: "var(--iris-radius-md, 6px)",
|
|
12550
|
+
borderTopRightRadius: "var(--iris-radius-md, 6px)",
|
|
12551
|
+
background: "var(--iris-surface)"
|
|
12552
|
+
}
|
|
12553
|
+
},
|
|
12554
|
+
unique.map(
|
|
12555
|
+
(tab) => vue.h(
|
|
12556
|
+
"button",
|
|
12557
|
+
{
|
|
12558
|
+
key: tab.key,
|
|
12559
|
+
type: "button",
|
|
12560
|
+
role: "tab",
|
|
12561
|
+
"data-iris-table-tab": tab.key,
|
|
12562
|
+
"aria-selected": activeTab.value === tab.key ? "true" : "false",
|
|
12563
|
+
onClick: () => onApply(tab),
|
|
12564
|
+
style: {
|
|
12565
|
+
border: "none",
|
|
12566
|
+
background: "transparent",
|
|
12567
|
+
color: activeTab.value === tab.key ? "var(--iris-primary)" : "var(--iris-foreground)",
|
|
12568
|
+
cursor: "pointer",
|
|
12569
|
+
font: "inherit",
|
|
12570
|
+
fontWeight: activeTab.value === tab.key ? "600" : "400",
|
|
12571
|
+
padding: "0 var(--iris-space-xxs, 4px)"
|
|
12572
|
+
}
|
|
12573
|
+
},
|
|
12574
|
+
tab.label
|
|
12575
|
+
)
|
|
12576
|
+
)
|
|
12577
|
+
);
|
|
10572
12578
|
}
|
|
12579
|
+
|
|
12580
|
+
// src/primitives/table/Table.ts
|
|
10573
12581
|
var IrisTable = vue.defineComponent({
|
|
10574
12582
|
name: "IrisTable",
|
|
10575
12583
|
inheritAttrs: false,
|
|
10576
|
-
props:
|
|
10577
|
-
columns: {
|
|
10578
|
-
type: Array,
|
|
10579
|
-
required: true
|
|
10580
|
-
},
|
|
10581
|
-
data: {
|
|
10582
|
-
type: Array,
|
|
10583
|
-
required: false,
|
|
10584
|
-
default: void 0
|
|
10585
|
-
},
|
|
10586
|
-
rowKey: { type: String, default: "id" },
|
|
10587
|
-
...tableControlProps,
|
|
10588
|
-
striped: { type: Boolean, default: false },
|
|
10589
|
-
editConfig: {
|
|
10590
|
-
type: Object,
|
|
10591
|
-
default: void 0
|
|
10592
|
-
},
|
|
10593
|
-
bordered: { type: Boolean, default: true },
|
|
10594
|
-
/** Enable per-column resize handles. Combine with `v-model:columnWidths` for persistence. */
|
|
10595
|
-
resizableColumns: { type: Boolean, default: false },
|
|
10596
|
-
/** Controlled column widths in px. */
|
|
10597
|
-
columnWidths: {
|
|
10598
|
-
type: Object,
|
|
10599
|
-
default: void 0
|
|
10600
|
-
},
|
|
10601
|
-
/** Enable virtual scrolling for the body. */
|
|
10602
|
-
virtualScroll: {
|
|
10603
|
-
type: Object,
|
|
10604
|
-
default: void 0
|
|
10605
|
-
},
|
|
10606
|
-
/** Show the loading state instead of rows. */
|
|
10607
|
-
loading: { type: Boolean, default: false },
|
|
10608
|
-
/** Show the error state instead of rows (takes precedence over loading). */
|
|
10609
|
-
error: { type: Boolean, default: false },
|
|
10610
|
-
onRetry: { type: Function, default: void 0 },
|
|
10611
|
-
/** Render only the horizontally-visible columns (+ pinned + overscan) for wide tables. */
|
|
10612
|
-
columnVirtualization: { type: Boolean, default: false },
|
|
10613
|
-
/**
|
|
10614
|
-
* Enable WAI-ARIA grid keyboard navigation: the table becomes `role="grid"`
|
|
10615
|
-
* and Arrow / Home / End / Page Up·Down move a roving cell focus across the
|
|
10616
|
-
* data cells. Off by default; opt-in and additive (no effect on mouse / Tab
|
|
10617
|
-
* behavior). Pairs best without virtualization (the focused cell must be
|
|
10618
|
-
* rendered) and does not hijack keystrokes while a cell is being edited.
|
|
10619
|
-
*/
|
|
10620
|
-
keyboardNavigation: { type: Boolean, default: false },
|
|
10621
|
-
/**
|
|
10622
|
-
* Enable rectangular cell-range selection (Excel-style). Click starts a
|
|
10623
|
-
* range; Shift+Click or Shift+Arrow extends it; Escape clears it.
|
|
10624
|
-
* Cells within the range get `data-iris-cell-selected="true"`.
|
|
10625
|
-
*/
|
|
10626
|
-
cellRange: { type: Boolean, default: false },
|
|
10627
|
-
/**
|
|
10628
|
-
* Render an expandable detail panel beneath a row. Providing this adds a
|
|
10629
|
-
* leading expand-toggle column; clicking it reveals a full-width detail row.
|
|
10630
|
-
* (Not applied in the virtual-scroll path.)
|
|
10631
|
-
*/
|
|
10632
|
-
renderDetail: {
|
|
10633
|
-
type: Function,
|
|
10634
|
-
default: void 0
|
|
10635
|
-
},
|
|
10636
|
-
/** Which rows can expand a detail panel. Defaults to all rows when `renderDetail` is set. */
|
|
10637
|
-
rowExpandable: {
|
|
10638
|
-
type: Function,
|
|
10639
|
-
default: void 0
|
|
10640
|
-
},
|
|
10641
|
-
/** Initially-expanded row keys (uncontrolled). */
|
|
10642
|
-
defaultExpandedRowKeys: {
|
|
10643
|
-
type: Array,
|
|
10644
|
-
default: void 0
|
|
10645
|
-
},
|
|
10646
|
-
/**
|
|
10647
|
-
* Read a row's child rows to render the table as a TREE. Providing this
|
|
10648
|
-
* enables tree mode: `data` is treated as the root rows, each row's first
|
|
10649
|
-
* cell gains a depth indent + an expand/collapse toggle (when it has
|
|
10650
|
-
* children), and the expand state reuses `defaultExpandedRowKeys` /
|
|
10651
|
-
* `expandedRowsChange`. Column sort reorders siblings hierarchically (each
|
|
10652
|
-
* level sorted, structure kept), and tree rows virtualize like flat rows
|
|
10653
|
-
* when `virtualScroll` is set (unless `renderDetail` is also used, since
|
|
10654
|
-
* detail panels are variable-height).
|
|
10655
|
-
*/
|
|
10656
|
-
getSubRows: {
|
|
10657
|
-
type: Function,
|
|
10658
|
-
default: void 0
|
|
10659
|
-
},
|
|
10660
|
-
/**
|
|
10661
|
-
* Cascade multi-row selection through the complete tree supplied by
|
|
10662
|
-
* `getSubRows`. Selecting a branch selects every descendant (including
|
|
10663
|
-
* collapsed rows); partially selected branches render indeterminate.
|
|
10664
|
-
* Ignored outside tree mode and for non-multi selection.
|
|
10665
|
-
*/
|
|
10666
|
-
treeSelectionCascade: { type: Boolean, default: false }
|
|
10667
|
-
},
|
|
12584
|
+
props: tableProps,
|
|
10668
12585
|
emits: {
|
|
10669
12586
|
"update:selection": (_value) => true,
|
|
10670
12587
|
"update:sort": (_value) => true,
|
|
12588
|
+
"update:multiSortState": (_value) => true,
|
|
12589
|
+
multiSortChange: (_value) => true,
|
|
10671
12590
|
"update:columnWidths": (_value) => true,
|
|
12591
|
+
/** Controlled columnVisibility channel (parent owns the map). */
|
|
12592
|
+
"update:columnVisibility": (_value) => true,
|
|
10672
12593
|
rowClick: (_row, _index) => true,
|
|
10673
12594
|
rowDblclick: (_row, _index) => true,
|
|
10674
12595
|
cellEdit: (_payload) => true,
|
|
10675
12596
|
expandedRowsChange: (_keys) => true
|
|
10676
12597
|
},
|
|
10677
|
-
setup(props, { slots, attrs, emit }) {
|
|
10678
|
-
|
|
10679
|
-
const style = document.createElement("style");
|
|
10680
|
-
style.id = "iris-table-row-styles";
|
|
10681
|
-
style.textContent = `
|
|
10682
|
-
[data-iris-table] [role="row"]:hover {
|
|
10683
|
-
--iris-cell-bg: var(--iris-surface-hover);
|
|
10684
|
-
}
|
|
10685
|
-
[data-iris-table-row-selected="true"] {
|
|
10686
|
-
--iris-cell-bg: var(--iris-surface-selected);
|
|
10687
|
-
}
|
|
10688
|
-
`;
|
|
10689
|
-
document.head.appendChild(style);
|
|
10690
|
-
}
|
|
12598
|
+
setup(props, { slots, attrs, emit, expose }) {
|
|
12599
|
+
ensureTableStyles();
|
|
10691
12600
|
const { t } = useI18n();
|
|
10692
|
-
const
|
|
12601
|
+
const densityState = vue.ref("comfortable");
|
|
12602
|
+
const effectiveDensity = vue.computed(() => {
|
|
12603
|
+
if (props.densityToggle) return densityState.value;
|
|
12604
|
+
return props.density === "compact" || props.density === "cozy" ? props.density : "comfortable";
|
|
12605
|
+
});
|
|
12606
|
+
const cycleDensity = () => {
|
|
12607
|
+
densityState.value = densityState.value === "comfortable" ? "compact" : densityState.value === "compact" ? "cozy" : "comfortable";
|
|
12608
|
+
};
|
|
12609
|
+
const importController = useTableImport(
|
|
12610
|
+
() => props.importPreview,
|
|
12611
|
+
() => props.toolbar?.onImport
|
|
12612
|
+
);
|
|
12613
|
+
const responsiveWidth = vue.ref(0);
|
|
12614
|
+
const internalWidths = vue.ref({});
|
|
12615
|
+
const effectiveWidths = vue.computed(() => {
|
|
12616
|
+
if (props.columnWidths) return props.columnWidths;
|
|
12617
|
+
return internalWidths.value;
|
|
12618
|
+
});
|
|
12619
|
+
const sourceDisplayColumns = vue.computed(() => {
|
|
12620
|
+
const vis = props.columnVisibility;
|
|
12621
|
+
if (!vis) return props.columns;
|
|
12622
|
+
return props.columns.filter((c) => vis[c.key] !== false);
|
|
12623
|
+
});
|
|
12624
|
+
const detectedTypes = vue.ref({});
|
|
12625
|
+
const detectTypesDone = vue.ref(false);
|
|
12626
|
+
const detectedDisplayColumns = vue.computed(() => {
|
|
12627
|
+
if (!props.autoDetectTypes || Object.keys(detectedTypes.value).length === 0) {
|
|
12628
|
+
return sourceDisplayColumns.value;
|
|
12629
|
+
}
|
|
12630
|
+
return applyDetectedTableTypes(sourceDisplayColumns.value, detectedTypes.value);
|
|
12631
|
+
});
|
|
12632
|
+
const responsiveLeadingWidth = vue.computed(
|
|
12633
|
+
() => (props.rowDrag ? DRAG_COL_WIDTH : 0) + (props.seq ? SEQ_COL_WIDTH : 0) + (props.renderDetail !== void 0 ? EXPAND_COL_WIDTH : 0) + (props.selectable !== "none" ? SELECTION_COL_WIDTH : 0)
|
|
12634
|
+
);
|
|
12635
|
+
const responsiveWidthOf = (column) => {
|
|
12636
|
+
const width = effectiveWidths.value[column.key] ?? resolveInitialWidth(column);
|
|
12637
|
+
return Number.isFinite(width) && width >= 0 ? width : resolveInitialWidth(column);
|
|
12638
|
+
};
|
|
12639
|
+
const responsiveResult = vue.computed(
|
|
12640
|
+
() => props.responsive ? computeResponsiveTableColumns(
|
|
12641
|
+
detectedDisplayColumns.value,
|
|
12642
|
+
responsiveWidth.value,
|
|
12643
|
+
responsiveLeadingWidth.value,
|
|
12644
|
+
responsiveWidthOf
|
|
12645
|
+
) : { columns: detectedDisplayColumns.value, overflow: false }
|
|
12646
|
+
);
|
|
12647
|
+
const responsiveDisplayColumns = vue.computed(
|
|
12648
|
+
() => responsiveResult.value.columns
|
|
12649
|
+
);
|
|
12650
|
+
const responsiveOverflow = vue.computed(() => responsiveResult.value.overflow);
|
|
12651
|
+
const displayColumns = vue.computed(
|
|
12652
|
+
() => responsiveDisplayColumns.value
|
|
12653
|
+
);
|
|
12654
|
+
const grouped = vue.computed(
|
|
12655
|
+
() => displayColumns.value.some((c) => c.children && c.children.length > 0)
|
|
12656
|
+
);
|
|
10693
12657
|
const leafColumns = vue.computed(
|
|
10694
|
-
() => grouped.value ? core.flattenLeafColumns(
|
|
12658
|
+
() => grouped.value ? core.flattenLeafColumns(displayColumns.value) : displayColumns.value
|
|
12659
|
+
);
|
|
12660
|
+
const headerMatrix = vue.computed(
|
|
12661
|
+
() => grouped.value ? core.buildHeaderMatrix(displayColumns.value) : null
|
|
12662
|
+
);
|
|
12663
|
+
const remoteSort = vue.computed(() => props.proxyConfig?.remoteSort === true);
|
|
12664
|
+
const remoteFilter = vue.computed(() => props.proxyConfig?.remoteFilter === true);
|
|
12665
|
+
const proxyCtrl = useTableProxy({
|
|
12666
|
+
proxyConfig: () => props.proxyConfig,
|
|
12667
|
+
remoteSort,
|
|
12668
|
+
remoteFilter,
|
|
12669
|
+
multiSort: () => props.multiSort,
|
|
12670
|
+
sort: () => props.sort,
|
|
12671
|
+
defaultSort: props.defaultSort,
|
|
12672
|
+
multiSortState: () => props.multiSortState,
|
|
12673
|
+
defaultMultiSort: props.defaultMultiSort,
|
|
12674
|
+
filters: () => props.filters,
|
|
12675
|
+
filterValues: () => props.filterValues
|
|
12676
|
+
});
|
|
12677
|
+
const tableLoading = vue.computed(
|
|
12678
|
+
() => proxyCtrl.proxy.value ? proxyCtrl.state.value.loading : props.loading
|
|
12679
|
+
);
|
|
12680
|
+
const tableError = vue.computed(
|
|
12681
|
+
() => proxyCtrl.proxy.value ? proxyCtrl.state.value.error !== null : props.error
|
|
12682
|
+
);
|
|
12683
|
+
const handleRetry = () => {
|
|
12684
|
+
if (proxyCtrl.proxy.value) void proxyCtrl.proxy.value.refetch();
|
|
12685
|
+
props.onRetry?.();
|
|
12686
|
+
};
|
|
12687
|
+
const retry = vue.computed(() => proxyCtrl.proxy.value ? handleRetry : props.onRetry);
|
|
12688
|
+
const localRowsOverride = vue.ref(null);
|
|
12689
|
+
vue.watch(
|
|
12690
|
+
() => props.data,
|
|
12691
|
+
() => {
|
|
12692
|
+
if (localRowsOverride.value !== null) localRowsOverride.value = null;
|
|
12693
|
+
}
|
|
12694
|
+
);
|
|
12695
|
+
const tableData = vue.computed(
|
|
12696
|
+
() => proxyCtrl.proxy.value ? proxyCtrl.liveData.value : localRowsOverride.value ?? props.data ?? []
|
|
12697
|
+
);
|
|
12698
|
+
vue.watch(
|
|
12699
|
+
[() => props.autoDetectTypes, tableData, () => props.columns],
|
|
12700
|
+
() => {
|
|
12701
|
+
if (!props.autoDetectTypes || detectTypesDone.value || tableData.value.length === 0) return;
|
|
12702
|
+
detectTypesDone.value = true;
|
|
12703
|
+
const next = {};
|
|
12704
|
+
for (const column of core.flattenLeafColumns(props.columns)) {
|
|
12705
|
+
const candidate = column;
|
|
12706
|
+
if (candidate.formula) continue;
|
|
12707
|
+
next[column.key] = core.detectColumnType(
|
|
12708
|
+
tableData.value.map((row) => getCellValue(row, candidate))
|
|
12709
|
+
);
|
|
12710
|
+
}
|
|
12711
|
+
detectedTypes.value = next;
|
|
12712
|
+
},
|
|
12713
|
+
{ immediate: true }
|
|
10695
12714
|
);
|
|
10696
|
-
const headerMatrix = vue.computed(() => grouped.value ? core.buildHeaderMatrix(props.columns) : null);
|
|
10697
12715
|
const {
|
|
10698
12716
|
sortState: internalSort,
|
|
10699
12717
|
cycleSort,
|
|
12718
|
+
setSort,
|
|
10700
12719
|
sortComparator,
|
|
10701
|
-
sortedData: sortedRows
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
|
|
12720
|
+
sortedData: sortedRows,
|
|
12721
|
+
multiSortState,
|
|
12722
|
+
cycleMultiSort
|
|
12723
|
+
} = useTableSort(tableData, {
|
|
12724
|
+
leafColumns,
|
|
12725
|
+
sort: vue.computed(() => props.sort),
|
|
12726
|
+
defaultSort: props.defaultSort,
|
|
12727
|
+
onSortChange: (next) => {
|
|
12728
|
+
emit("update:sort", next);
|
|
12729
|
+
if (remoteSort.value) proxyCtrl.setParams({ sort: next });
|
|
12730
|
+
},
|
|
12731
|
+
multiSort: () => props.multiSort,
|
|
12732
|
+
multiSortState: () => props.multiSortState,
|
|
12733
|
+
defaultMultiSort: props.defaultMultiSort,
|
|
12734
|
+
onMultiSortChange: (next) => {
|
|
12735
|
+
emit("update:multiSortState", next);
|
|
12736
|
+
emit("multiSortChange", next);
|
|
12737
|
+
if (remoteSort.value) proxyCtrl.setParams({ sorts: next });
|
|
12738
|
+
}
|
|
12739
|
+
});
|
|
12740
|
+
const tableViews = createTableViewsController({
|
|
12741
|
+
config: () => props.views,
|
|
12742
|
+
sort: internalSort,
|
|
12743
|
+
setSort,
|
|
12744
|
+
onActiveViewChange: (key) => props.onActiveViewChange?.(key)
|
|
12745
|
+
});
|
|
12746
|
+
const sortedData = vue.computed(() => remoteSort.value ? tableData.value : sortedRows.value);
|
|
12747
|
+
vue.watch([internalSort, () => props.multiSort, remoteSort, () => proxyCtrl.proxy.value], () => {
|
|
12748
|
+
if (!proxyCtrl.proxy.value || !remoteSort.value || props.multiSort) return;
|
|
12749
|
+
proxyCtrl.setParams({ sort: internalSort.value });
|
|
12750
|
+
});
|
|
12751
|
+
vue.watch([multiSortState, () => props.multiSort, remoteSort, () => proxyCtrl.proxy.value], () => {
|
|
12752
|
+
if (!proxyCtrl.proxy.value || !remoteSort.value || !props.multiSort) return;
|
|
12753
|
+
proxyCtrl.setParams({ sorts: multiSortState.value });
|
|
12754
|
+
});
|
|
12755
|
+
const formDraft = vue.ref({});
|
|
12756
|
+
const formApplied = vue.ref({});
|
|
12757
|
+
const formFieldSignature = vue.computed(
|
|
12758
|
+
() => (props.formConfig?.fields ?? []).map((f) => `${f.key}=${f.defaultValue ?? ""}`).join("\0")
|
|
12759
|
+
);
|
|
12760
|
+
vue.watch(
|
|
12761
|
+
formFieldSignature,
|
|
12762
|
+
() => {
|
|
12763
|
+
formDraft.value = core.seedFormValues(props.formConfig?.fields);
|
|
12764
|
+
formApplied.value = {};
|
|
12765
|
+
},
|
|
12766
|
+
{ immediate: true }
|
|
12767
|
+
);
|
|
12768
|
+
const setFormValue = (key, value) => {
|
|
12769
|
+
if (formDraft.value[key] === value) return;
|
|
12770
|
+
formDraft.value = { ...formDraft.value, [key]: value };
|
|
12771
|
+
};
|
|
12772
|
+
const mergedProxyFilters = (form) => mergeFilterValues(core.mergeFormFilters(props.filters ?? {}, form), props.filterValues ?? {});
|
|
12773
|
+
const handleFormSubmit = () => {
|
|
12774
|
+
const values = core.buildFormValues(props.formConfig?.fields, formDraft.value);
|
|
12775
|
+
props.formConfig?.onSearch?.(values);
|
|
12776
|
+
formApplied.value = values;
|
|
12777
|
+
if (proxyCtrl.proxy.value) {
|
|
12778
|
+
proxyCtrl.setParams({ filters: mergedProxyFilters(values), page: 1 });
|
|
12779
|
+
}
|
|
12780
|
+
};
|
|
12781
|
+
const handleFormReset = () => {
|
|
12782
|
+
const defaults = core.seedFormValues(props.formConfig?.fields);
|
|
12783
|
+
formDraft.value = defaults;
|
|
12784
|
+
const values = core.buildFormValues(props.formConfig?.fields, defaults);
|
|
12785
|
+
formApplied.value = values;
|
|
12786
|
+
props.formConfig?.onReset?.(values);
|
|
12787
|
+
if (proxyCtrl.proxy.value) {
|
|
12788
|
+
if (!proxyCtrl.setParams({ filters: mergedProxyFilters(values), page: 1 })) {
|
|
12789
|
+
void proxyCtrl.refetch();
|
|
12790
|
+
}
|
|
10709
12791
|
}
|
|
12792
|
+
};
|
|
12793
|
+
vue.watch(
|
|
12794
|
+
[formApplied, () => props.filters, () => props.filterValues],
|
|
12795
|
+
() => {
|
|
12796
|
+
if (proxyCtrl.proxy.value && remoteFilter.value) {
|
|
12797
|
+
proxyCtrl.setParams({
|
|
12798
|
+
filters: mergedProxyFilters(formApplied.value)
|
|
12799
|
+
});
|
|
12800
|
+
}
|
|
12801
|
+
},
|
|
12802
|
+
{ immediate: true }
|
|
10710
12803
|
);
|
|
10711
12804
|
const selControlled = vue.computed(() => props.selection !== void 0);
|
|
10712
12805
|
const selectionModel = core.createSelectionModel({
|
|
@@ -10749,18 +12842,56 @@ var IrisTable = vue.defineComponent({
|
|
|
10749
12842
|
if (typeof v === "string" || typeof v === "number") return v;
|
|
10750
12843
|
return index;
|
|
10751
12844
|
};
|
|
10752
|
-
const treeMode = vue.computed(() => props.getSubRows !== void 0);
|
|
12845
|
+
const treeMode = vue.computed(() => props.getSubRows !== void 0 || props.lazyLoad !== void 0);
|
|
12846
|
+
const lazyChildren = vue.ref(/* @__PURE__ */ new Map());
|
|
12847
|
+
const lazyLoading = vue.ref(/* @__PURE__ */ new Set());
|
|
12848
|
+
let lazyEpoch = 0;
|
|
12849
|
+
vue.watch(
|
|
12850
|
+
() => proxyCtrl.proxy.value ? proxyCtrl.state.value.data : props.data,
|
|
12851
|
+
() => {
|
|
12852
|
+
lazyChildren.value = /* @__PURE__ */ new Map();
|
|
12853
|
+
lazyLoading.value = /* @__PURE__ */ new Set();
|
|
12854
|
+
lazyEpoch += 1;
|
|
12855
|
+
}
|
|
12856
|
+
);
|
|
12857
|
+
const lazyChildrenOf = (row) => {
|
|
12858
|
+
const key = String(row[props.rowKey]);
|
|
12859
|
+
return lazyChildren.value.get(key) ?? props.getSubRows?.(row);
|
|
12860
|
+
};
|
|
10753
12861
|
const flatTree = vue.computed(
|
|
10754
|
-
() => treeMode.value ? core.flattenTree(
|
|
12862
|
+
() => treeMode.value ? core.flattenTree(sortedData.value, {
|
|
10755
12863
|
getKey: (r) => String(r[props.rowKey]),
|
|
10756
12864
|
// With an active sort, sort each level's children by the same
|
|
10757
|
-
// comparator so the whole tree reorders hierarchically.
|
|
10758
|
-
|
|
12865
|
+
// comparator so the whole tree reorders hierarchically. Lazy-loaded
|
|
12866
|
+
// children win over `getSubRows` and still participate.
|
|
12867
|
+
getChildren: sortComparator.value ? core.withSortedChildren(lazyChildrenOf, sortComparator.value) : lazyChildrenOf,
|
|
10759
12868
|
isExpanded: (k) => expandedKeys.value.includes(k)
|
|
10760
12869
|
}) : null
|
|
10761
12870
|
);
|
|
12871
|
+
const filteredData = vue.computed(() => {
|
|
12872
|
+
if (remoteFilter.value) return sortedData.value;
|
|
12873
|
+
const merged = proxyCtrl.proxy.value ? props.filters ?? {} : core.mergeFormFilters(props.filters ?? {}, formApplied.value);
|
|
12874
|
+
const active = Object.entries(merged).filter(([, v]) => v != null && v !== "");
|
|
12875
|
+
const checkedEntries = Object.entries(props.filterValues ?? {}).filter(
|
|
12876
|
+
([, values]) => values.length > 0
|
|
12877
|
+
);
|
|
12878
|
+
if (active.length === 0 && checkedEntries.length === 0) return sortedData.value;
|
|
12879
|
+
return sortedData.value.filter((row) => {
|
|
12880
|
+
const textOk = active.every(([key, value]) => {
|
|
12881
|
+
const col = displayColumns.value.find((c) => c.key === key);
|
|
12882
|
+
if (!col) return true;
|
|
12883
|
+
return String(getCellValue(row, col) ?? "").toLowerCase().includes(value.toLowerCase());
|
|
12884
|
+
});
|
|
12885
|
+
const setsOk = checkedEntries.every(([key, values]) => {
|
|
12886
|
+
const col = displayColumns.value.find((c) => c.key === key);
|
|
12887
|
+
if (!col) return true;
|
|
12888
|
+
return values.includes(String(getCellValue(row, col) ?? ""));
|
|
12889
|
+
});
|
|
12890
|
+
return textOk && setsOk;
|
|
12891
|
+
});
|
|
12892
|
+
});
|
|
10762
12893
|
const bodyData = vue.computed(
|
|
10763
|
-
() => flatTree.value ? flatTree.value.map((t2) => t2.row) :
|
|
12894
|
+
() => flatTree.value ? flatTree.value.map((t2) => t2.row) : filteredData.value
|
|
10764
12895
|
);
|
|
10765
12896
|
const cascadingTreeSelection = vue.computed(
|
|
10766
12897
|
() => props.treeSelectionCascade && props.selectable === "multi" && treeMode.value
|
|
@@ -10782,7 +12913,7 @@ var IrisTable = vue.defineComponent({
|
|
|
10782
12913
|
if (children && children.length > 0) walk(children, key);
|
|
10783
12914
|
}
|
|
10784
12915
|
};
|
|
10785
|
-
walk(
|
|
12916
|
+
walk(sortedData.value);
|
|
10786
12917
|
return nodes;
|
|
10787
12918
|
});
|
|
10788
12919
|
const compactTreeSelectionSeed = (keys) => {
|
|
@@ -10855,25 +12986,27 @@ var IrisTable = vue.defineComponent({
|
|
|
10855
12986
|
selectionModel.set([...allRowIds.value]);
|
|
10856
12987
|
};
|
|
10857
12988
|
const editingCellId = vue.ref(null);
|
|
12989
|
+
const editingColumnKey = vue.ref(null);
|
|
10858
12990
|
const editingDraft = vue.ref("");
|
|
10859
12991
|
const editError = vue.ref(null);
|
|
10860
12992
|
const editorInputRef = vue.ref(null);
|
|
10861
|
-
const cellId = (rowIdent, colKey) => `${rowIdent}::${colKey}`;
|
|
10862
12993
|
const beginEdit = (row, column, rowIdent) => {
|
|
10863
12994
|
if (!column.editable) return;
|
|
10864
12995
|
editingCellId.value = cellId(rowIdent, column.key);
|
|
10865
|
-
|
|
12996
|
+
editingColumnKey.value = column.key;
|
|
12997
|
+
const current = getCellValue(row, column);
|
|
10866
12998
|
editingDraft.value = current == null ? "" : String(current);
|
|
10867
12999
|
editError.value = null;
|
|
10868
13000
|
void vue.nextTick(() => editorInputRef.value?.focus());
|
|
10869
13001
|
};
|
|
10870
13002
|
const commitEdit = (row, column, rowIndex) => {
|
|
10871
13003
|
if (editingCellId.value === null) return;
|
|
10872
|
-
const oldValue =
|
|
13004
|
+
const oldValue = getCellValue(row, column);
|
|
10873
13005
|
const draft = editingDraft.value;
|
|
10874
13006
|
const newValue = column.editor === "number" ? draft === "" || Number.isNaN(Number(draft)) ? oldValue : Number(draft) : draft;
|
|
10875
13007
|
if (column.editRules && column.editRules.length > 0) {
|
|
10876
|
-
|
|
13008
|
+
const context = { rows: tableData.value, columnKey: column.key };
|
|
13009
|
+
core.validateEditRulesAsync(column.editRules, draft, row, false, context).then((r) => {
|
|
10877
13010
|
if (!r.valid) {
|
|
10878
13011
|
editError.value = r.messages[0] ?? null;
|
|
10879
13012
|
return;
|
|
@@ -10896,67 +13029,272 @@ var IrisTable = vue.defineComponent({
|
|
|
10896
13029
|
emit("cellEdit", { row, column, oldValue, newValue, rowIndex });
|
|
10897
13030
|
}
|
|
10898
13031
|
};
|
|
13032
|
+
const writeCellValue = (row, column, rowIndex, oldValue, newValue) => {
|
|
13033
|
+
if (newValue === oldValue) return;
|
|
13034
|
+
emit("cellEdit", { row, column, oldValue, newValue, rowIndex });
|
|
13035
|
+
if (proxyCtrl.proxy.value) {
|
|
13036
|
+
const id = rowId(row, rowIndex);
|
|
13037
|
+
const idx = proxyCtrl.liveData.value.findIndex((r, i) => rowId(r, i) === id);
|
|
13038
|
+
if (idx >= 0) {
|
|
13039
|
+
const key = column.dataIndex ?? column.key;
|
|
13040
|
+
const next = { ...proxyCtrl.liveData.value[idx], [key]: newValue };
|
|
13041
|
+
proxyCtrl.liveData.value = [
|
|
13042
|
+
...proxyCtrl.liveData.value.slice(0, idx),
|
|
13043
|
+
next,
|
|
13044
|
+
...proxyCtrl.liveData.value.slice(idx + 1)
|
|
13045
|
+
];
|
|
13046
|
+
}
|
|
13047
|
+
}
|
|
13048
|
+
};
|
|
10899
13049
|
const finishCommit = (row, column, rowIndex, oldValue, newValue) => {
|
|
10900
13050
|
editError.value = null;
|
|
10901
13051
|
editingCellId.value = null;
|
|
10902
|
-
|
|
10903
|
-
|
|
13052
|
+
editingColumnKey.value = null;
|
|
13053
|
+
writeCellValue(row, column, rowIndex, oldValue, newValue);
|
|
13054
|
+
};
|
|
13055
|
+
const cancelEdit = () => {
|
|
13056
|
+
editError.value = null;
|
|
13057
|
+
editingCellId.value = null;
|
|
13058
|
+
editingColumnKey.value = null;
|
|
13059
|
+
};
|
|
13060
|
+
const rowMode = vue.computed(() => props.editConfig?.mode === "row");
|
|
13061
|
+
const rowSessions = vue.ref(/* @__PURE__ */ new Map());
|
|
13062
|
+
const rowEditing = vue.ref(null);
|
|
13063
|
+
const rowEditorRefs = /* @__PURE__ */ new Map();
|
|
13064
|
+
const currentRowFor = (k) => bodyData.value.find((r, i) => rowId(r, i) === k);
|
|
13065
|
+
const beginRowEdit = (row, rowIndex, focusColKey) => {
|
|
13066
|
+
const k = rowId(row, rowIndex);
|
|
13067
|
+
const editableCols = leafColumns.value.filter((c) => c.editable);
|
|
13068
|
+
if (editableCols.length === 0) return;
|
|
13069
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
13070
|
+
for (const col of editableCols) {
|
|
13071
|
+
const current = getCellValue(row, col);
|
|
13072
|
+
sessions.set(cellId(k, col.key), {
|
|
13073
|
+
draft: current == null ? "" : String(current),
|
|
13074
|
+
error: null
|
|
13075
|
+
});
|
|
13076
|
+
}
|
|
13077
|
+
rowSessions.value = sessions;
|
|
13078
|
+
rowEditing.value = { k, idx: rowIndex };
|
|
13079
|
+
const focusKey = focusColKey && editableCols.some((c) => c.key === focusColKey) ? focusColKey : editableCols[0].key;
|
|
13080
|
+
void vue.nextTick(() => rowEditorRefs.get(focusKey)?.focus());
|
|
13081
|
+
};
|
|
13082
|
+
const commitRowSession = (k, column, rowIndex, id) => {
|
|
13083
|
+
const session = rowSessions.value.get(id);
|
|
13084
|
+
if (!session) return;
|
|
13085
|
+
const row = currentRowFor(k);
|
|
13086
|
+
if (!row) return;
|
|
13087
|
+
const oldValue = getCellValue(row, column);
|
|
13088
|
+
const draft = session.draft;
|
|
13089
|
+
const newValue = column.editor === "number" ? draft === "" || Number.isNaN(Number(draft)) ? oldValue : Number(draft) : draft;
|
|
13090
|
+
if (column.editRules && column.editRules.length > 0) {
|
|
13091
|
+
const context = { rows: tableData.value, columnKey: column.key };
|
|
13092
|
+
core.validateEditRulesAsync(column.editRules, draft, row, false, context).then((r) => {
|
|
13093
|
+
if (!rowSessions.value.has(id)) return;
|
|
13094
|
+
if (!r.valid) {
|
|
13095
|
+
const s = rowSessions.value.get(id);
|
|
13096
|
+
if (s) s.error = r.messages[0] ?? null;
|
|
13097
|
+
return;
|
|
13098
|
+
}
|
|
13099
|
+
finishRowCommit(row, column, rowIndex, oldValue, newValue, id);
|
|
13100
|
+
});
|
|
13101
|
+
return;
|
|
13102
|
+
}
|
|
13103
|
+
if (column.validate) {
|
|
13104
|
+
const error = column.validate(newValue, row);
|
|
13105
|
+
if (error) {
|
|
13106
|
+
const s = rowSessions.value.get(id);
|
|
13107
|
+
if (s) s.error = error;
|
|
13108
|
+
return;
|
|
13109
|
+
}
|
|
13110
|
+
}
|
|
13111
|
+
finishRowCommit(row, column, rowIndex, oldValue, newValue, id);
|
|
13112
|
+
};
|
|
13113
|
+
const finishRowCommit = (row, column, rowIndex, oldValue, newValue, id) => {
|
|
13114
|
+
rowSessions.value.delete(id);
|
|
13115
|
+
if (rowSessions.value.size === 0) rowEditing.value = null;
|
|
13116
|
+
writeCellValue(row, column, rowIndex, oldValue, newValue);
|
|
13117
|
+
};
|
|
13118
|
+
const cancelRowEdit = () => {
|
|
13119
|
+
rowSessions.value = /* @__PURE__ */ new Map();
|
|
13120
|
+
rowEditing.value = null;
|
|
13121
|
+
};
|
|
13122
|
+
const switchRowEdit = (row, rowIndex, focusColKey) => {
|
|
13123
|
+
const editing = rowEditing.value;
|
|
13124
|
+
if (editing !== null) {
|
|
13125
|
+
for (const [id] of rowSessions.value) {
|
|
13126
|
+
const colKey = id.slice(id.indexOf("::") + 2);
|
|
13127
|
+
const col = leafColumns.value.find((c) => c.key === colKey);
|
|
13128
|
+
if (!col) continue;
|
|
13129
|
+
commitRowSession(editing.k, col, editing.idx, id);
|
|
13130
|
+
if (rowSessions.value.get(id)?.error != null) return;
|
|
13131
|
+
}
|
|
13132
|
+
}
|
|
13133
|
+
beginRowEdit(row, rowIndex, focusColKey);
|
|
13134
|
+
};
|
|
13135
|
+
const handleRowModeCellClick = (row, col, index, k) => {
|
|
13136
|
+
if (rowEditing.value?.k === k) {
|
|
13137
|
+
const id = cellId(k, col.key);
|
|
13138
|
+
if (col.editable && !rowSessions.value.has(id)) {
|
|
13139
|
+
const current = getCellValue(row, col);
|
|
13140
|
+
rowSessions.value.set(id, {
|
|
13141
|
+
draft: current == null ? "" : String(current),
|
|
13142
|
+
error: null
|
|
13143
|
+
});
|
|
13144
|
+
void vue.nextTick(() => rowEditorRefs.get(col.key)?.focus());
|
|
13145
|
+
}
|
|
13146
|
+
} else {
|
|
13147
|
+
switchRowEdit(row, index, col.key);
|
|
10904
13148
|
}
|
|
10905
13149
|
};
|
|
10906
|
-
const
|
|
10907
|
-
|
|
10908
|
-
|
|
13150
|
+
const editorRenderContext = {
|
|
13151
|
+
rowEditorRefs,
|
|
13152
|
+
editorInputRef,
|
|
13153
|
+
editingDraft,
|
|
13154
|
+
editError,
|
|
13155
|
+
commitEdit,
|
|
13156
|
+
cancelEdit,
|
|
13157
|
+
commitRowSession,
|
|
13158
|
+
cancelRowEdit,
|
|
13159
|
+
editPreview: props.editPreview,
|
|
13160
|
+
previewValue: (row, col, draft) => {
|
|
13161
|
+
const raw = col.editor === "number" ? draft === "" || Number.isNaN(Number(draft)) ? getCellValue(row, col) : Number(draft) : draft;
|
|
13162
|
+
return col.formatter?.(core.applyTableMask(raw, col), row) ?? "";
|
|
13163
|
+
}
|
|
10909
13164
|
};
|
|
10910
|
-
const
|
|
13165
|
+
const buildRowSessionContent = (row, col, index, k, editCellId, session) => renderRowSessionContent(editorRenderContext, row, col, index, k, editCellId, session);
|
|
13166
|
+
const buildCellEditContent = (row, col, index, editCellId) => renderCellEditContent(editorRenderContext, row, col, index, editCellId);
|
|
13167
|
+
const buildTreeIndent = (treeMeta, row) => vue.h(
|
|
13168
|
+
"span",
|
|
13169
|
+
{
|
|
13170
|
+
"data-iris-table-tree-indent": "",
|
|
13171
|
+
style: {
|
|
13172
|
+
display: "inline-flex",
|
|
13173
|
+
alignItems: "center",
|
|
13174
|
+
flex: "none",
|
|
13175
|
+
paddingLeft: `${treeMeta.depth * 16}px`
|
|
13176
|
+
}
|
|
13177
|
+
},
|
|
13178
|
+
treeMeta.hasChildren || props.lazyLoad !== void 0 && !lazyChildren.value.has(treeMeta.key) ? [
|
|
13179
|
+
vue.h(
|
|
13180
|
+
"button",
|
|
13181
|
+
{
|
|
13182
|
+
type: "button",
|
|
13183
|
+
"data-iris-table-tree-toggle": "",
|
|
13184
|
+
"data-iris-tree-loading": lazyLoading.value.has(treeMeta.key) ? "" : void 0,
|
|
13185
|
+
"aria-expanded": treeMeta.expanded ? "true" : "false",
|
|
13186
|
+
"aria-label": t(treeMeta.expanded ? "treeSelect.collapse" : "treeSelect.expand"),
|
|
13187
|
+
onClick: (e) => {
|
|
13188
|
+
e.stopPropagation();
|
|
13189
|
+
if (treeMeta.hasChildren) {
|
|
13190
|
+
expansion.toggle(treeMeta.key);
|
|
13191
|
+
return;
|
|
13192
|
+
}
|
|
13193
|
+
if (lazyLoading.value.has(treeMeta.key)) return;
|
|
13194
|
+
lazyLoading.value = new Set(lazyLoading.value).add(treeMeta.key);
|
|
13195
|
+
const clearLoading = () => {
|
|
13196
|
+
const next = new Set(lazyLoading.value);
|
|
13197
|
+
next.delete(treeMeta.key);
|
|
13198
|
+
lazyLoading.value = next;
|
|
13199
|
+
};
|
|
13200
|
+
try {
|
|
13201
|
+
const epoch = lazyEpoch;
|
|
13202
|
+
props.lazyLoad(row, (children) => {
|
|
13203
|
+
if (epoch !== lazyEpoch) return;
|
|
13204
|
+
lazyChildren.value.set(treeMeta.key, children);
|
|
13205
|
+
if (children && children.length > 0) {
|
|
13206
|
+
expansion.toggle(treeMeta.key);
|
|
13207
|
+
}
|
|
13208
|
+
clearLoading();
|
|
13209
|
+
});
|
|
13210
|
+
} catch {
|
|
13211
|
+
clearLoading();
|
|
13212
|
+
}
|
|
13213
|
+
},
|
|
13214
|
+
style: {
|
|
13215
|
+
border: "none",
|
|
13216
|
+
background: "transparent",
|
|
13217
|
+
cursor: "pointer",
|
|
13218
|
+
padding: "0",
|
|
13219
|
+
marginRight: "4px",
|
|
13220
|
+
font: "inherit",
|
|
13221
|
+
color: "var(--iris-foreground)",
|
|
13222
|
+
transform: treeMeta.expanded ? "rotate(90deg)" : "none",
|
|
13223
|
+
transition: "transform 150ms"
|
|
13224
|
+
}
|
|
13225
|
+
},
|
|
13226
|
+
"\u25B6"
|
|
13227
|
+
)
|
|
13228
|
+
] : [
|
|
13229
|
+
vue.h("span", {
|
|
13230
|
+
"aria-hidden": "true",
|
|
13231
|
+
style: { display: "inline-block", width: "16px" }
|
|
13232
|
+
})
|
|
13233
|
+
]
|
|
13234
|
+
);
|
|
10911
13235
|
vue.watch(
|
|
10912
13236
|
() => leafColumns.value,
|
|
10913
13237
|
(cols) => {
|
|
10914
13238
|
const seeded = { ...internalWidths.value };
|
|
13239
|
+
let changed = false;
|
|
10915
13240
|
for (const col of cols) {
|
|
10916
|
-
if (seeded[col.key] === void 0)
|
|
13241
|
+
if (seeded[col.key] === void 0) {
|
|
13242
|
+
seeded[col.key] = resolveInitialWidth(col);
|
|
13243
|
+
changed = true;
|
|
13244
|
+
}
|
|
10917
13245
|
}
|
|
10918
|
-
internalWidths.value = seeded;
|
|
13246
|
+
if (changed) internalWidths.value = seeded;
|
|
10919
13247
|
},
|
|
10920
13248
|
{ immediate: true, deep: false }
|
|
10921
13249
|
);
|
|
10922
|
-
const effectiveWidths = vue.computed(() => {
|
|
10923
|
-
if (props.columnWidths) return props.columnWidths;
|
|
10924
|
-
return internalWidths.value;
|
|
10925
|
-
});
|
|
10926
13250
|
const setColumnWidths = (next) => {
|
|
10927
13251
|
if (props.columnWidths === void 0) internalWidths.value = next;
|
|
10928
13252
|
emit("update:columnWidths", next);
|
|
10929
13253
|
};
|
|
10930
13254
|
const onHeaderClick = (column) => {
|
|
10931
|
-
|
|
10932
|
-
|
|
10933
|
-
|
|
10934
|
-
|
|
10935
|
-
|
|
10936
|
-
const
|
|
10937
|
-
|
|
10938
|
-
const color = isActive ? "var(--iris-primary)" : "var(--iris-muted)";
|
|
13255
|
+
if (props.multiSort) cycleMultiSort(column);
|
|
13256
|
+
else cycleSort(column);
|
|
13257
|
+
};
|
|
13258
|
+
const multiSortSeq = (col) => {
|
|
13259
|
+
if (!props.multiSort) return null;
|
|
13260
|
+
const idx = multiSortState.value.findIndex((s) => s.key === col.key);
|
|
13261
|
+
if (idx <= 0) return null;
|
|
10939
13262
|
return vue.h(
|
|
10940
13263
|
"span",
|
|
10941
13264
|
{
|
|
10942
|
-
"
|
|
13265
|
+
"data-iris-sort-seq": "",
|
|
10943
13266
|
style: {
|
|
10944
|
-
display: "inline-flex",
|
|
10945
|
-
flexDirection: "column",
|
|
10946
13267
|
marginInlineStart: "var(--iris-space-xxs, 4px)",
|
|
10947
|
-
lineHeight: "0.6",
|
|
10948
13268
|
fontSize: "var(--iris-font-size-xs, 12px)",
|
|
10949
|
-
color
|
|
13269
|
+
color: "var(--iris-muted)"
|
|
10950
13270
|
}
|
|
10951
13271
|
},
|
|
10952
|
-
|
|
10953
|
-
vue.h("span", { style: { opacity: direction === "asc" ? "1" : "0.45" } }, "\u25B2"),
|
|
10954
|
-
vue.h("span", { style: { opacity: direction === "desc" ? "1" : "0.45" } }, "\u25BC")
|
|
10955
|
-
]
|
|
13272
|
+
String(idx + 1)
|
|
10956
13273
|
);
|
|
10957
13274
|
};
|
|
13275
|
+
const ariaSortFor = (col) => {
|
|
13276
|
+
const state = props.multiSort ? multiSortState.value.find((s) => s.key === col.key) ?? null : internalSort.value;
|
|
13277
|
+
if (state?.key === col.key) return state.direction === "asc" ? "ascending" : "descending";
|
|
13278
|
+
return col.sortable ? "none" : void 0;
|
|
13279
|
+
};
|
|
13280
|
+
const sortIndicator = (col) => renderTableSortIndicator(col, {
|
|
13281
|
+
multiSort: props.multiSort,
|
|
13282
|
+
multiSortState: multiSortState.value,
|
|
13283
|
+
sort: internalSort.value
|
|
13284
|
+
});
|
|
13285
|
+
const renderFilterTrigger = (col, leaf) => renderTableFilterTrigger({
|
|
13286
|
+
column: col,
|
|
13287
|
+
leaf,
|
|
13288
|
+
active: (props.filterValues?.[col.key]?.length ?? 0) > 0,
|
|
13289
|
+
open: filterPanelState.value?.open === true && filterPanelState.value.colKey === col.key,
|
|
13290
|
+
label: t("table.filter"),
|
|
13291
|
+
onOpen: openFilterPanel
|
|
13292
|
+
});
|
|
13293
|
+
const leadTrackCount = () => (props.rowDrag ? 1 : 0) + (props.seq ? 1 : 0) + (hasDetail.value ? 1 : 0) + (props.selectable !== "none" ? 1 : 0);
|
|
10958
13294
|
const gridTemplate = vue.computed(() => {
|
|
10959
13295
|
const parts = [];
|
|
13296
|
+
if (props.rowDrag) parts.push(`${DRAG_COL_WIDTH}px`);
|
|
13297
|
+
if (props.seq) parts.push(`${SEQ_COL_WIDTH}px`);
|
|
10960
13298
|
if (hasDetail.value) parts.push(`${EXPAND_COL_WIDTH}px`);
|
|
10961
13299
|
if (props.selectable !== "none") parts.push(`${SELECTION_COL_WIDTH}px`);
|
|
10962
13300
|
for (const col of leafColumns.value) {
|
|
@@ -10971,70 +13309,45 @@ var IrisTable = vue.defineComponent({
|
|
|
10971
13309
|
cellRangeState.value = s;
|
|
10972
13310
|
})
|
|
10973
13311
|
);
|
|
10974
|
-
const isInRange = (row, col) => {
|
|
10975
|
-
const { anchor, active } = cellRangeState.value;
|
|
10976
|
-
if (!anchor || !active) return false;
|
|
10977
|
-
const minRow = Math.min(anchor.row, active.row);
|
|
10978
|
-
const maxRow = Math.max(anchor.row, active.row);
|
|
10979
|
-
const minCol = Math.min(anchor.col, active.col);
|
|
10980
|
-
const maxCol = Math.max(anchor.col, active.col);
|
|
10981
|
-
return row >= minRow && row <= maxRow && col >= minCol && col <= maxCol;
|
|
10982
|
-
};
|
|
10983
13312
|
const rootRef = vue.ref(null);
|
|
13313
|
+
let responsiveObserver = null;
|
|
13314
|
+
const measureResponsiveWidth = () => {
|
|
13315
|
+
responsiveWidth.value = props.responsive && rootRef.value ? rootRef.value.clientWidth : 0;
|
|
13316
|
+
};
|
|
13317
|
+
const updateResponsiveObserver = () => {
|
|
13318
|
+
responsiveObserver?.disconnect();
|
|
13319
|
+
responsiveObserver = null;
|
|
13320
|
+
responsiveWidth.value = 0;
|
|
13321
|
+
if (!props.responsive || !rootRef.value || typeof ResizeObserver === "undefined") return;
|
|
13322
|
+
measureResponsiveWidth();
|
|
13323
|
+
responsiveObserver = new ResizeObserver(measureResponsiveWidth);
|
|
13324
|
+
responsiveObserver.observe(rootRef.value);
|
|
13325
|
+
};
|
|
13326
|
+
vue.onMounted(updateResponsiveObserver);
|
|
13327
|
+
vue.watch(() => props.responsive, updateResponsiveObserver);
|
|
13328
|
+
vue.onBeforeUnmount(() => {
|
|
13329
|
+
responsiveObserver?.disconnect();
|
|
13330
|
+
responsiveObserver = null;
|
|
13331
|
+
});
|
|
13332
|
+
const rowTarget = createTableRowTarget(() => rootRef.value);
|
|
13333
|
+
const { scrollTo: scrollToRow, goTo: goToRow } = rowTarget;
|
|
13334
|
+
vue.onBeforeUnmount(rowTarget.dispose);
|
|
10984
13335
|
const focusedCell = vue.ref(null);
|
|
10985
|
-
const
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10996
|
-
|
|
10997
|
-
const target = e.target;
|
|
10998
|
-
if (target.dataset.gridRow === void 0) return;
|
|
10999
|
-
e.preventDefault();
|
|
11000
|
-
const current = focusedCell.value ?? { row: 0, col: 0 };
|
|
11001
|
-
const next = core.nextGridCell(current, e.key, {
|
|
11002
|
-
rowCount: bodyData.value.length,
|
|
11003
|
-
colCount: leafColumns.value.length,
|
|
11004
|
-
pageSize: 10
|
|
11005
|
-
});
|
|
11006
|
-
focusedCell.value = next;
|
|
11007
|
-
const cell = rootRef.value?.querySelector(
|
|
11008
|
-
`[data-grid-row="${next.row}"][data-grid-col="${next.col}"]`
|
|
11009
|
-
);
|
|
11010
|
-
cell?.focus();
|
|
11011
|
-
};
|
|
11012
|
-
const CELL_RANGE_ARROW_KEYS = /* @__PURE__ */ new Set(["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"]);
|
|
11013
|
-
const handleCellRangeKey = (e) => {
|
|
11014
|
-
if (!props.cellRange) return;
|
|
11015
|
-
if (e.key === "Escape") {
|
|
11016
|
-
cellRangeCtrl.clearRange();
|
|
11017
|
-
return;
|
|
11018
|
-
}
|
|
11019
|
-
if (!e.shiftKey || !CELL_RANGE_ARROW_KEYS.has(e.key)) return;
|
|
11020
|
-
const target = e.target;
|
|
11021
|
-
const rowAttr = target.dataset.irisCellRow;
|
|
11022
|
-
const colAttr = target.dataset.irisCellCol;
|
|
11023
|
-
if (rowAttr === void 0 || colAttr === void 0) return;
|
|
11024
|
-
e.preventDefault();
|
|
11025
|
-
const anchor = cellRangeCtrl.getState().anchor;
|
|
11026
|
-
const active = anchor ? cellRangeCtrl.getState().active ?? { row: Number(rowAttr), col: Number(colAttr) } : { row: Number(rowAttr), col: Number(colAttr) };
|
|
11027
|
-
let nextRow = active.row;
|
|
11028
|
-
let nextCol = active.col;
|
|
11029
|
-
if (e.key === "ArrowUp") nextRow = Math.max(0, nextRow - 1);
|
|
11030
|
-
else if (e.key === "ArrowDown") nextRow = Math.min(bodyData.value.length - 1, nextRow + 1);
|
|
11031
|
-
else if (e.key === "ArrowLeft") nextCol = Math.max(0, nextCol - 1);
|
|
11032
|
-
else nextCol = Math.min(leafColumns.value.length - 1, nextCol + 1);
|
|
11033
|
-
cellRangeCtrl.extendRange(nextRow, nextCol);
|
|
11034
|
-
};
|
|
13336
|
+
const keyboard = createTableKeyboard({
|
|
13337
|
+
keyboardNavigation: () => props.keyboardNavigation,
|
|
13338
|
+
cellRange: () => props.cellRange,
|
|
13339
|
+
clipConfig: () => props.clipConfig,
|
|
13340
|
+
rows: () => bodyData.value,
|
|
13341
|
+
columns: () => leafColumns.value,
|
|
13342
|
+
root: () => rootRef.value,
|
|
13343
|
+
focused: focusedCell,
|
|
13344
|
+
range: cellRangeCtrl,
|
|
13345
|
+
rangeState: cellRangeState
|
|
13346
|
+
});
|
|
13347
|
+
const { handleRootKeyDown, isInRange, activeCellRange, copyActiveRange } = keyboard;
|
|
11035
13348
|
const scrollLeft = vue.ref(0);
|
|
11036
13349
|
const viewportWidth = vue.ref(0);
|
|
11037
|
-
const colTrack = (i) => (
|
|
13350
|
+
const colTrack = (i) => leadTrackCount() + 1 + i;
|
|
11038
13351
|
if (typeof ResizeObserver !== "undefined") {
|
|
11039
13352
|
let ro = null;
|
|
11040
13353
|
vue.onMounted(() => {
|
|
@@ -11051,27 +13364,19 @@ var IrisTable = vue.defineComponent({
|
|
|
11051
13364
|
ro = null;
|
|
11052
13365
|
});
|
|
11053
13366
|
}
|
|
11054
|
-
const visibleColSet = vue.computed(
|
|
11055
|
-
|
|
11056
|
-
|
|
11057
|
-
|
|
11058
|
-
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
|
|
11062
|
-
|
|
11063
|
-
});
|
|
11064
|
-
const set = /* @__PURE__ */ new Set();
|
|
11065
|
-
for (let i = w.startIndex; i <= w.endIndex; i += 1) set.add(i);
|
|
11066
|
-
cols.forEach((col, i) => {
|
|
11067
|
-
if (col.pinned) set.add(i);
|
|
11068
|
-
});
|
|
11069
|
-
return set;
|
|
11070
|
-
});
|
|
13367
|
+
const visibleColSet = vue.computed(
|
|
13368
|
+
() => computeVisibleColSet(
|
|
13369
|
+
props.columnVirtualization,
|
|
13370
|
+
leafColumns.value,
|
|
13371
|
+
scrollLeft.value,
|
|
13372
|
+
viewportWidth.value,
|
|
13373
|
+
effectiveWidths.value
|
|
13374
|
+
)
|
|
13375
|
+
);
|
|
11071
13376
|
const pinnedOffsets = vue.computed(() => {
|
|
11072
13377
|
const map = {};
|
|
11073
13378
|
const widthOf = (col) => effectiveWidths.value[col.key] ?? resolveInitialWidth(col);
|
|
11074
|
-
let left = (hasDetail.value ? EXPAND_COL_WIDTH : 0) + (props.selectable !== "none" ? SELECTION_COL_WIDTH : 0);
|
|
13379
|
+
let left = (props.rowDrag ? DRAG_COL_WIDTH : 0) + (props.seq ? SEQ_COL_WIDTH : 0) + (hasDetail.value ? EXPAND_COL_WIDTH : 0) + (props.selectable !== "none" ? SELECTION_COL_WIDTH : 0);
|
|
11075
13380
|
for (const col of leafColumns.value) {
|
|
11076
13381
|
if (col.pinned === "left") {
|
|
11077
13382
|
map[col.key] = { side: "left", offset: left };
|
|
@@ -11127,126 +13432,449 @@ var IrisTable = vue.defineComponent({
|
|
|
11127
13432
|
}
|
|
11128
13433
|
});
|
|
11129
13434
|
};
|
|
13435
|
+
const pinnedDragHandle = createTablePinnedDrag({
|
|
13436
|
+
enabled: () => props.pinnedDrag === true,
|
|
13437
|
+
columns: () => leafColumns.value,
|
|
13438
|
+
widthOf: (column) => effectiveWidths.value[column.key] ?? resolveInitialWidth(column),
|
|
13439
|
+
onColumnPinnedChange: props.onColumnPinnedChange,
|
|
13440
|
+
onPinnedCountChange: props.onPinnedCountChange
|
|
13441
|
+
});
|
|
13442
|
+
const rowDragCtrl = core.createSortable();
|
|
13443
|
+
const rowDragState = vue.shallowRef(rowDragCtrl.getState());
|
|
13444
|
+
vue.onBeforeUnmount(
|
|
13445
|
+
rowDragCtrl.subscribe((s) => {
|
|
13446
|
+
rowDragState.value = s;
|
|
13447
|
+
})
|
|
13448
|
+
);
|
|
13449
|
+
const colDragCtrl = core.createSortable();
|
|
13450
|
+
const colDragState = vue.shallowRef(colDragCtrl.getState());
|
|
13451
|
+
vue.onBeforeUnmount(
|
|
13452
|
+
colDragCtrl.subscribe((s) => {
|
|
13453
|
+
colDragState.value = s;
|
|
13454
|
+
})
|
|
13455
|
+
);
|
|
13456
|
+
const rowRectsRef = vue.ref([]);
|
|
13457
|
+
const colRectsRef = vue.ref([]);
|
|
13458
|
+
const handleRowDragPointerDown = (e, rowId2) => {
|
|
13459
|
+
if (!props.rowDrag || e.button !== 0) return;
|
|
13460
|
+
e.preventDefault();
|
|
13461
|
+
rowDragCtrl.press(rowId2, e.clientX, e.clientY);
|
|
13462
|
+
};
|
|
13463
|
+
const handleRowDragPointerMove = (e) => {
|
|
13464
|
+
if (!props.rowDrag) return;
|
|
13465
|
+
if (rowDragCtrl.isPending()) {
|
|
13466
|
+
const started = rowDragCtrl.tryStart(e.clientX, e.clientY);
|
|
13467
|
+
if (started) {
|
|
13468
|
+
const rects = [];
|
|
13469
|
+
rootRef.value?.querySelectorAll("[data-iris-row-drag-handle]").forEach((el) => {
|
|
13470
|
+
const r = el.getBoundingClientRect();
|
|
13471
|
+
const id = el.getAttribute("data-iris-row-drag-handle");
|
|
13472
|
+
if (id) rects.push({ id, left: r.left, top: r.top, width: r.width, height: r.height });
|
|
13473
|
+
});
|
|
13474
|
+
rowRectsRef.value = rects;
|
|
13475
|
+
}
|
|
13476
|
+
}
|
|
13477
|
+
if (rowDragCtrl.getState().activeId !== null) {
|
|
13478
|
+
rowDragCtrl.moveOver({ x: e.clientX, y: e.clientY }, rowRectsRef.value);
|
|
13479
|
+
}
|
|
13480
|
+
};
|
|
13481
|
+
const handleRowDragPointerUp = () => {
|
|
13482
|
+
if (!props.rowDrag) return;
|
|
13483
|
+
if (rowDragCtrl.isPending()) {
|
|
13484
|
+
rowDragCtrl.cancel();
|
|
13485
|
+
return;
|
|
13486
|
+
}
|
|
13487
|
+
const { activeId, overId } = rowDragCtrl.end();
|
|
13488
|
+
if (activeId !== null && overId !== null && activeId !== overId) {
|
|
13489
|
+
const rows = [...bodyData.value];
|
|
13490
|
+
const from = rows.findIndex((r, i) => String(rowId(r, i)) === activeId);
|
|
13491
|
+
const to = rows.findIndex((r, i) => String(rowId(r, i)) === overId);
|
|
13492
|
+
if (from >= 0 && to >= 0 && from !== to) {
|
|
13493
|
+
const [moved] = rows.splice(from, 1);
|
|
13494
|
+
rows.splice(to, 0, moved);
|
|
13495
|
+
if (proxyCtrl.proxy.value) proxyCtrl.liveData.value = rows;
|
|
13496
|
+
else localRowsOverride.value = rows;
|
|
13497
|
+
props.onDataChange?.(rows);
|
|
13498
|
+
props.rowDrag.onReorder(rows);
|
|
13499
|
+
}
|
|
13500
|
+
}
|
|
13501
|
+
rowRectsRef.value = [];
|
|
13502
|
+
};
|
|
13503
|
+
const handleRowDragPointerLeave = () => {
|
|
13504
|
+
if (props.rowDrag && rowDragCtrl.getState().activeId !== null) {
|
|
13505
|
+
rowDragCtrl.cancel();
|
|
13506
|
+
}
|
|
13507
|
+
};
|
|
13508
|
+
const handleColDragPointerDown = (e, colKey) => {
|
|
13509
|
+
if (!props.columnDrag || e.button !== 0) return;
|
|
13510
|
+
e.preventDefault();
|
|
13511
|
+
e.stopPropagation();
|
|
13512
|
+
colDragCtrl.press(colKey, e.clientX, e.clientY);
|
|
13513
|
+
};
|
|
13514
|
+
const handleColDragPointerMove = (e) => {
|
|
13515
|
+
if (!props.columnDrag) return;
|
|
13516
|
+
if (colDragCtrl.isPending()) {
|
|
13517
|
+
const started = colDragCtrl.tryStart(e.clientX, e.clientY);
|
|
13518
|
+
if (started) {
|
|
13519
|
+
const rects = [];
|
|
13520
|
+
rootRef.value?.querySelectorAll("[data-iris-table-header]").forEach((el) => {
|
|
13521
|
+
const r = el.getBoundingClientRect();
|
|
13522
|
+
const id = el.getAttribute("data-iris-table-header");
|
|
13523
|
+
if (id) rects.push({ id, left: r.left, top: r.top, width: r.width, height: r.height });
|
|
13524
|
+
});
|
|
13525
|
+
colRectsRef.value = rects;
|
|
13526
|
+
}
|
|
13527
|
+
}
|
|
13528
|
+
if (colDragCtrl.getState().activeId !== null) {
|
|
13529
|
+
colDragCtrl.moveOver({ x: e.clientX, y: e.clientY }, colRectsRef.value);
|
|
13530
|
+
}
|
|
13531
|
+
};
|
|
13532
|
+
const handleColDragPointerUp = () => {
|
|
13533
|
+
if (!props.columnDrag) return;
|
|
13534
|
+
if (colDragCtrl.isPending()) {
|
|
13535
|
+
colDragCtrl.cancel();
|
|
13536
|
+
return;
|
|
13537
|
+
}
|
|
13538
|
+
const { activeId, overId } = colDragCtrl.end();
|
|
13539
|
+
if (activeId !== null && overId !== null && activeId !== overId) {
|
|
13540
|
+
const next = [...leafColumns.value];
|
|
13541
|
+
const from = next.findIndex((c) => c.key === activeId);
|
|
13542
|
+
const to = next.findIndex((c) => c.key === overId);
|
|
13543
|
+
if (from >= 0 && to >= 0 && from !== to) {
|
|
13544
|
+
const [moved] = next.splice(from, 1);
|
|
13545
|
+
next.splice(to, 0, moved);
|
|
13546
|
+
props.columnDrag.onReorder(next);
|
|
13547
|
+
}
|
|
13548
|
+
}
|
|
13549
|
+
colRectsRef.value = [];
|
|
13550
|
+
};
|
|
13551
|
+
const spanOccupy = /* @__PURE__ */ new Set();
|
|
13552
|
+
const tableExpose = {
|
|
13553
|
+
loadData: (rows) => {
|
|
13554
|
+
if (proxyCtrl.proxy.value) proxyCtrl.liveData.value = rows;
|
|
13555
|
+
else localRowsOverride.value = rows;
|
|
13556
|
+
props.onDataChange?.(rows);
|
|
13557
|
+
},
|
|
13558
|
+
reloadData: () => {
|
|
13559
|
+
void proxyCtrl.refetch();
|
|
13560
|
+
},
|
|
13561
|
+
commitProxy: (overrides) => {
|
|
13562
|
+
proxyCtrl.setParams(overrides);
|
|
13563
|
+
},
|
|
13564
|
+
getProxyInfo: () => {
|
|
13565
|
+
if (!proxyCtrl.proxy.value) return null;
|
|
13566
|
+
const s = proxyCtrl.state.value;
|
|
13567
|
+
return { page: s.params.page, pageSize: s.params.pageSize, total: s.total };
|
|
13568
|
+
},
|
|
13569
|
+
removeRows: (keys) => {
|
|
13570
|
+
const { rows, removedKeys } = core.removeRowsFromList(tableData.value, props.rowKey, keys);
|
|
13571
|
+
if (removedKeys.size === 0) return;
|
|
13572
|
+
if (proxyCtrl.proxy.value) proxyCtrl.liveData.value = rows;
|
|
13573
|
+
else localRowsOverride.value = rows;
|
|
13574
|
+
const selected = displaySelection.value;
|
|
13575
|
+
const nextSelection = selected.filter((key) => !removedKeys.has(key));
|
|
13576
|
+
if (nextSelection.length !== selected.length) {
|
|
13577
|
+
rebaseToProp();
|
|
13578
|
+
selectionModel.set(nextSelection);
|
|
13579
|
+
}
|
|
13580
|
+
props.onDataChange?.(rows);
|
|
13581
|
+
},
|
|
13582
|
+
getFilteredData: () => [...bodyData.value],
|
|
13583
|
+
exportCurrentViewCsv: () => exportCsv(bodyData.value, leafColumns.value),
|
|
13584
|
+
exportMultiCsv: () => {
|
|
13585
|
+
const current = exportCsv(bodyData.value, leafColumns.value);
|
|
13586
|
+
const names = props.exportNames;
|
|
13587
|
+
if (!names || names.length === 0) return current;
|
|
13588
|
+
const segments = [`# current${current ? `
|
|
13589
|
+
${current}` : ""}`];
|
|
13590
|
+
for (const entry of names) {
|
|
13591
|
+
if (!entry.key) continue;
|
|
13592
|
+
const refCsv = core.toCsvRows(entry.ref());
|
|
13593
|
+
segments.push(`# ${entry.key}${refCsv ? `
|
|
13594
|
+
${refCsv}` : ""}`);
|
|
13595
|
+
}
|
|
13596
|
+
return segments.join("\n\n");
|
|
13597
|
+
},
|
|
13598
|
+
compareStates: core.compareStates,
|
|
13599
|
+
scrollToRow,
|
|
13600
|
+
goToRow
|
|
13601
|
+
};
|
|
13602
|
+
expose(tableExpose);
|
|
13603
|
+
const buildFormSection = () => renderFormSection({
|
|
13604
|
+
formConfig: props.formConfig,
|
|
13605
|
+
t,
|
|
13606
|
+
formDraft,
|
|
13607
|
+
setFormValue,
|
|
13608
|
+
handleFormSubmit,
|
|
13609
|
+
handleFormReset
|
|
13610
|
+
});
|
|
13611
|
+
const buildToolbarSection = () => renderToolbarSection({
|
|
13612
|
+
toolbar: props.toolbar,
|
|
13613
|
+
selectable: props.selectable,
|
|
13614
|
+
displaySelection,
|
|
13615
|
+
proxyCtrl,
|
|
13616
|
+
t,
|
|
13617
|
+
importFileInput: importController.importFileInput,
|
|
13618
|
+
onImportFile: importController.handleImportFile,
|
|
13619
|
+
densityToggle: props.densityToggle,
|
|
13620
|
+
effectiveDensity: effectiveDensity.value,
|
|
13621
|
+
onDensityToggle: cycleDensity
|
|
13622
|
+
});
|
|
13623
|
+
const buildPagerSection = () => renderPagerSection({ proxyCtrl, proxyConfig: props.proxyConfig });
|
|
13624
|
+
const contextMenuState = vue.ref(null);
|
|
13625
|
+
const contextAnchorRef = vue.ref(null);
|
|
13626
|
+
const contextMenuRef = vue.ref(null);
|
|
13627
|
+
const closeContextMenu = () => {
|
|
13628
|
+
if (contextMenuState.value) contextMenuState.value.open = false;
|
|
13629
|
+
};
|
|
13630
|
+
const handleContextMenu = (e, row, col, idx, ci) => {
|
|
13631
|
+
if (!props.contextMenu) return;
|
|
13632
|
+
e.preventDefault();
|
|
13633
|
+
contextAnchorRef.value = {
|
|
13634
|
+
getBoundingClientRect: () => ({
|
|
13635
|
+
left: e.clientX,
|
|
13636
|
+
top: e.clientY,
|
|
13637
|
+
right: e.clientX,
|
|
13638
|
+
bottom: e.clientY,
|
|
13639
|
+
width: 0,
|
|
13640
|
+
height: 0,
|
|
13641
|
+
x: e.clientX,
|
|
13642
|
+
y: e.clientY,
|
|
13643
|
+
toJSON() {
|
|
13644
|
+
}
|
|
13645
|
+
})
|
|
13646
|
+
};
|
|
13647
|
+
const params = {
|
|
13648
|
+
row,
|
|
13649
|
+
column: col,
|
|
13650
|
+
rowIndex: idx,
|
|
13651
|
+
columnIndex: ci
|
|
13652
|
+
};
|
|
13653
|
+
contextMenuState.value = { open: true, items: props.contextMenu.items(params), params };
|
|
13654
|
+
};
|
|
13655
|
+
const contextMenuOpen = vue.computed(() => contextMenuState.value?.open === true);
|
|
13656
|
+
const { floatingStyles: contextMenuStyles } = useFloating({
|
|
13657
|
+
anchor: contextAnchorRef,
|
|
13658
|
+
floating: contextMenuRef,
|
|
13659
|
+
open: contextMenuOpen,
|
|
13660
|
+
placement: "bottom-start",
|
|
13661
|
+
// Cursor-anchored menu, vxe parity: with a zero-size anchor at the
|
|
13662
|
+
// viewport edge, flip/shift would clamp the coordinates away from the
|
|
13663
|
+
// cursor (React parity — deliberately disabled).
|
|
13664
|
+
flip: false,
|
|
13665
|
+
shift: false
|
|
13666
|
+
});
|
|
13667
|
+
useDismiss({
|
|
13668
|
+
enabled: contextMenuOpen,
|
|
13669
|
+
exclude: [contextMenuRef],
|
|
13670
|
+
onDismiss: closeContextMenu
|
|
13671
|
+
});
|
|
13672
|
+
vue.watch(contextMenuOpen, (open) => {
|
|
13673
|
+
if (typeof document === "undefined") return;
|
|
13674
|
+
if (open) document.addEventListener("scroll", closeContextMenu, true);
|
|
13675
|
+
else document.removeEventListener("scroll", closeContextMenu, true);
|
|
13676
|
+
});
|
|
13677
|
+
vue.onScopeDispose(() => {
|
|
13678
|
+
if (typeof document === "undefined") return;
|
|
13679
|
+
document.removeEventListener("scroll", closeContextMenu, true);
|
|
13680
|
+
});
|
|
13681
|
+
const buildContextMenuSection = () => renderContextMenuSection({
|
|
13682
|
+
state: contextMenuState,
|
|
13683
|
+
styles: contextMenuStyles,
|
|
13684
|
+
menuRef: contextMenuRef,
|
|
13685
|
+
close: closeContextMenu,
|
|
13686
|
+
contextMenu: props.contextMenu
|
|
13687
|
+
});
|
|
13688
|
+
const filterPanelState = vue.ref(null);
|
|
13689
|
+
const filterAnchorRef = vue.ref(null);
|
|
13690
|
+
const filterPanelRef = vue.ref(null);
|
|
13691
|
+
const filterDraft = vue.ref([]);
|
|
13692
|
+
const closeFilterPanel = () => {
|
|
13693
|
+
if (filterPanelState.value) filterPanelState.value.open = false;
|
|
13694
|
+
};
|
|
13695
|
+
const openFilterPanel = (e, colKey) => {
|
|
13696
|
+
e.stopPropagation();
|
|
13697
|
+
filterAnchorRef.value = e.currentTarget;
|
|
13698
|
+
filterDraft.value = [...props.filterValues?.[colKey] ?? []];
|
|
13699
|
+
filterPanelState.value = { open: true, colKey };
|
|
13700
|
+
};
|
|
13701
|
+
const filterPanelOpen = vue.computed(() => filterPanelState.value?.open === true);
|
|
13702
|
+
const { floatingStyles: filterPanelStyles } = useFloating({
|
|
13703
|
+
anchor: filterAnchorRef,
|
|
13704
|
+
floating: filterPanelRef,
|
|
13705
|
+
open: filterPanelOpen,
|
|
13706
|
+
placement: "bottom-start"
|
|
13707
|
+
});
|
|
13708
|
+
useDismiss({
|
|
13709
|
+
enabled: filterPanelOpen,
|
|
13710
|
+
exclude: [filterPanelRef, filterAnchorRef],
|
|
13711
|
+
onDismiss: closeFilterPanel
|
|
13712
|
+
});
|
|
13713
|
+
vue.watch(filterPanelOpen, (open) => {
|
|
13714
|
+
if (typeof document === "undefined") return;
|
|
13715
|
+
if (open) document.addEventListener("scroll", closeFilterPanel, true);
|
|
13716
|
+
else document.removeEventListener("scroll", closeFilterPanel, true);
|
|
13717
|
+
});
|
|
13718
|
+
vue.onScopeDispose(() => {
|
|
13719
|
+
if (typeof document === "undefined") return;
|
|
13720
|
+
document.removeEventListener("scroll", closeFilterPanel, true);
|
|
13721
|
+
});
|
|
13722
|
+
const applyFilterValues = (colKey, values) => {
|
|
13723
|
+
props.onFilterValuesChange?.({ ...props.filterValues ?? {}, [colKey]: values });
|
|
13724
|
+
};
|
|
13725
|
+
const clearFilterValues = (colKey) => {
|
|
13726
|
+
const next = { ...props.filterValues ?? {} };
|
|
13727
|
+
delete next[colKey];
|
|
13728
|
+
props.onFilterValuesChange?.(next);
|
|
13729
|
+
};
|
|
13730
|
+
const toggleFilterDraft = (value) => {
|
|
13731
|
+
filterDraft.value = filterDraft.value.includes(value) ? filterDraft.value.filter((v) => v !== value) : [...filterDraft.value, value];
|
|
13732
|
+
};
|
|
13733
|
+
const buildFilterPanelSection = () => renderFilterPanelSection({
|
|
13734
|
+
state: filterPanelState,
|
|
13735
|
+
styles: filterPanelStyles,
|
|
13736
|
+
panelRef: filterPanelRef,
|
|
13737
|
+
filterDraft,
|
|
13738
|
+
columns: displayColumns.value,
|
|
13739
|
+
filterValues: props.filterValues,
|
|
13740
|
+
t,
|
|
13741
|
+
close: closeFilterPanel,
|
|
13742
|
+
toggle: toggleFilterDraft,
|
|
13743
|
+
apply: applyFilterValues,
|
|
13744
|
+
clear: clearFilterValues
|
|
13745
|
+
});
|
|
11130
13746
|
return () => {
|
|
11131
13747
|
const showSelection = props.selectable !== "none";
|
|
11132
13748
|
const showDetail = hasDetail.value;
|
|
11133
|
-
const
|
|
11134
|
-
|
|
13749
|
+
const showDrag = props.rowDrag !== void 0;
|
|
13750
|
+
const showSeq = props.seq === true;
|
|
13751
|
+
spanOccupy.clear();
|
|
13752
|
+
const leadFlatHeaderCells = () => {
|
|
11135
13753
|
const cells = [];
|
|
11136
|
-
if (
|
|
13754
|
+
if (showDrag) {
|
|
11137
13755
|
cells.push(
|
|
11138
13756
|
vue.h("div", {
|
|
11139
|
-
key: "__expand__",
|
|
11140
13757
|
role: "columnheader",
|
|
11141
|
-
|
|
13758
|
+
key: "__drag__",
|
|
13759
|
+
"data-iris-table-header": "__drag",
|
|
13760
|
+
style: {
|
|
13761
|
+
display: "flex",
|
|
13762
|
+
alignItems: "center",
|
|
13763
|
+
justifyContent: "center",
|
|
13764
|
+
padding: "8px",
|
|
13765
|
+
background: "var(--iris-surface)",
|
|
13766
|
+
borderBottom: "1px solid var(--iris-border)"
|
|
13767
|
+
}
|
|
11142
13768
|
})
|
|
11143
13769
|
);
|
|
11144
13770
|
}
|
|
11145
|
-
if (
|
|
13771
|
+
if (showSeq) {
|
|
11146
13772
|
cells.push(
|
|
11147
|
-
vue.h(
|
|
11148
|
-
"
|
|
11149
|
-
|
|
11150
|
-
|
|
11151
|
-
|
|
11152
|
-
|
|
11153
|
-
|
|
11154
|
-
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
background: "var(--iris-surface)",
|
|
11161
|
-
borderBottom: "1px solid var(--iris-border)"
|
|
11162
|
-
}
|
|
11163
|
-
},
|
|
11164
|
-
props.selectable === "multi" ? [
|
|
11165
|
-
[
|
|
11166
|
-
vue.h(IrisCheckbox, {
|
|
11167
|
-
modelValue: allSelected.value ? true : someSelected.value ? "indeterminate" : false,
|
|
11168
|
-
size: "sm",
|
|
11169
|
-
ariaLabel: t("table.selectAll"),
|
|
11170
|
-
"onUpdate:modelValue": toggleAll
|
|
11171
|
-
}),
|
|
11172
|
-
props.selection && props.selection.length > 0 ? vue.h(
|
|
11173
|
-
"span",
|
|
11174
|
-
{
|
|
11175
|
-
"data-iris-table-selected-count": "",
|
|
11176
|
-
style: {
|
|
11177
|
-
marginInlineStart: "var(--iris-space-xs, 8px)",
|
|
11178
|
-
fontSize: "var(--iris-font-size-sm, 13px)",
|
|
11179
|
-
color: "var(--iris-muted)",
|
|
11180
|
-
whiteSpace: "nowrap"
|
|
11181
|
-
}
|
|
11182
|
-
},
|
|
11183
|
-
t("table.selectedCount", { count: String(props.selection.length) })
|
|
11184
|
-
) : null
|
|
11185
|
-
]
|
|
11186
|
-
] : ""
|
|
11187
|
-
)
|
|
13773
|
+
vue.h("div", {
|
|
13774
|
+
role: "columnheader",
|
|
13775
|
+
key: "__seq__",
|
|
13776
|
+
"data-iris-table-header": "__seq",
|
|
13777
|
+
style: {
|
|
13778
|
+
display: "flex",
|
|
13779
|
+
alignItems: "center",
|
|
13780
|
+
justifyContent: "center",
|
|
13781
|
+
padding: "8px",
|
|
13782
|
+
background: "var(--iris-surface)",
|
|
13783
|
+
borderBottom: "1px solid var(--iris-border)"
|
|
13784
|
+
}
|
|
13785
|
+
})
|
|
11188
13786
|
);
|
|
11189
13787
|
}
|
|
11190
|
-
|
|
11191
|
-
|
|
11192
|
-
|
|
11193
|
-
|
|
11194
|
-
|
|
11195
|
-
|
|
11196
|
-
|
|
11197
|
-
|
|
11198
|
-
|
|
11199
|
-
|
|
11200
|
-
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
|
|
11204
|
-
|
|
11205
|
-
|
|
11206
|
-
|
|
11207
|
-
|
|
11208
|
-
"aria-sort": sortable ? internalSort.value?.key === col.key ? internalSort.value.direction === "asc" ? "ascending" : "descending" : "none" : void 0,
|
|
11209
|
-
style: {
|
|
11210
|
-
gridColumn: `${lead + cell.colStart} / span ${cell.colSpan}`,
|
|
11211
|
-
gridRow: `${cell.level + 1} / span ${cell.rowSpan}`,
|
|
11212
|
-
display: "flex",
|
|
11213
|
-
alignItems: "center",
|
|
11214
|
-
justifyContent: isLeaf ? align === "right" ? "flex-end" : align === "center" ? "center" : "flex-start" : "center",
|
|
11215
|
-
padding: "8px var(--iris-padding-md)",
|
|
11216
|
-
cursor: sortable ? "pointer" : "default",
|
|
11217
|
-
userSelect: sortable ? "none" : "auto",
|
|
11218
|
-
background: "var(--iris-surface)",
|
|
11219
|
-
borderBottom: "1px solid var(--iris-border)",
|
|
11220
|
-
fontWeight: "600",
|
|
11221
|
-
fontSize: "var(--iris-font-size-md, 14px)",
|
|
11222
|
-
color: "var(--iris-foreground)",
|
|
11223
|
-
whiteSpace: "nowrap",
|
|
11224
|
-
overflow: "hidden",
|
|
11225
|
-
textOverflow: "ellipsis"
|
|
11226
|
-
}
|
|
11227
|
-
},
|
|
11228
|
-
[title, sortable ? sortIndicator(col) : null]
|
|
11229
|
-
)
|
|
11230
|
-
);
|
|
11231
|
-
}
|
|
13788
|
+
return cells;
|
|
13789
|
+
};
|
|
13790
|
+
const leadSummaryCells = () => {
|
|
13791
|
+
const cells = [];
|
|
13792
|
+
if (showDrag) {
|
|
13793
|
+
cells.push(
|
|
13794
|
+
vue.h("div", {
|
|
13795
|
+
key: "__drag",
|
|
13796
|
+
role: "cell",
|
|
13797
|
+
"data-iris-table-cell": "__drag",
|
|
13798
|
+
style: {
|
|
13799
|
+
display: "flex",
|
|
13800
|
+
alignItems: "center",
|
|
13801
|
+
justifyContent: "center",
|
|
13802
|
+
padding: "8px 12px"
|
|
13803
|
+
}
|
|
13804
|
+
})
|
|
13805
|
+
);
|
|
11232
13806
|
}
|
|
11233
|
-
|
|
11234
|
-
|
|
11235
|
-
|
|
11236
|
-
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
|
|
11240
|
-
|
|
11241
|
-
|
|
11242
|
-
|
|
11243
|
-
|
|
11244
|
-
|
|
11245
|
-
|
|
11246
|
-
|
|
11247
|
-
|
|
13807
|
+
if (showSeq) {
|
|
13808
|
+
cells.push(
|
|
13809
|
+
vue.h("div", {
|
|
13810
|
+
key: "__seq",
|
|
13811
|
+
role: "cell",
|
|
13812
|
+
"data-iris-table-cell": "__seq",
|
|
13813
|
+
style: {
|
|
13814
|
+
display: "flex",
|
|
13815
|
+
alignItems: "center",
|
|
13816
|
+
justifyContent: "center",
|
|
13817
|
+
padding: "8px 12px"
|
|
13818
|
+
}
|
|
13819
|
+
})
|
|
13820
|
+
);
|
|
13821
|
+
}
|
|
13822
|
+
if (showDetail) {
|
|
13823
|
+
cells.push(
|
|
13824
|
+
vue.h("div", {
|
|
13825
|
+
key: "__expand",
|
|
13826
|
+
role: "cell",
|
|
13827
|
+
"data-iris-table-cell": "__expand",
|
|
13828
|
+
style: {
|
|
13829
|
+
display: "flex",
|
|
13830
|
+
alignItems: "center",
|
|
13831
|
+
justifyContent: "center",
|
|
13832
|
+
padding: "8px 12px"
|
|
13833
|
+
}
|
|
13834
|
+
})
|
|
13835
|
+
);
|
|
13836
|
+
}
|
|
13837
|
+
if (showSelection) {
|
|
13838
|
+
cells.push(
|
|
13839
|
+
vue.h("div", {
|
|
13840
|
+
key: "__selection",
|
|
13841
|
+
role: "cell",
|
|
13842
|
+
"data-iris-table-cell": "__selection",
|
|
13843
|
+
style: {
|
|
13844
|
+
display: "flex",
|
|
13845
|
+
alignItems: "center",
|
|
13846
|
+
justifyContent: "center",
|
|
13847
|
+
padding: "8px 12px"
|
|
13848
|
+
}
|
|
13849
|
+
})
|
|
13850
|
+
);
|
|
13851
|
+
}
|
|
13852
|
+
return cells;
|
|
11248
13853
|
};
|
|
11249
|
-
const
|
|
13854
|
+
const buildGroupedHeader = (matrix) => renderGroupedHeader(
|
|
13855
|
+
{
|
|
13856
|
+
showDrag,
|
|
13857
|
+
showSeq,
|
|
13858
|
+
showDetail,
|
|
13859
|
+
showSelection,
|
|
13860
|
+
selectable: props.selectable,
|
|
13861
|
+
selection: props.selection,
|
|
13862
|
+
allSelected,
|
|
13863
|
+
someSelected,
|
|
13864
|
+
toggleAll,
|
|
13865
|
+
t,
|
|
13866
|
+
slots,
|
|
13867
|
+
onHeaderClick,
|
|
13868
|
+
ariaSortFor,
|
|
13869
|
+
sortIndicator,
|
|
13870
|
+
multiSortSeq,
|
|
13871
|
+
renderFilterTrigger,
|
|
13872
|
+
pinnedDragHandle,
|
|
13873
|
+
gridTemplate
|
|
13874
|
+
},
|
|
13875
|
+
matrix
|
|
13876
|
+
);
|
|
13877
|
+
const headerCells = leadFlatHeaderCells();
|
|
11250
13878
|
if (showDetail) {
|
|
11251
13879
|
headerCells.push(
|
|
11252
13880
|
vue.h("div", {
|
|
@@ -11291,14 +13919,15 @@ var IrisTable = vue.defineComponent({
|
|
|
11291
13919
|
)
|
|
11292
13920
|
);
|
|
11293
13921
|
}
|
|
11294
|
-
for (let ci = 0; ci <
|
|
11295
|
-
const col =
|
|
13922
|
+
for (let ci = 0; ci < leafColumns.value.length; ci += 1) {
|
|
13923
|
+
const col = leafColumns.value[ci];
|
|
11296
13924
|
if (visibleColSet.value && !visibleColSet.value.has(ci)) continue;
|
|
11297
13925
|
const align = col.align ?? "left";
|
|
11298
13926
|
const headerSlot = slots[`header.${col.key}`];
|
|
11299
13927
|
const title = headerSlot?.({ column: col }) ?? col.title;
|
|
11300
13928
|
wireResize(col);
|
|
11301
|
-
const
|
|
13929
|
+
const pinnedHandle = pinnedDragHandle(col);
|
|
13930
|
+
const handle = props.resizableColumns && !pinnedHandle ? vue.h("span", {
|
|
11302
13931
|
ref: (el) => {
|
|
11303
13932
|
getHandleRef(col.key).value = el ?? null;
|
|
11304
13933
|
},
|
|
@@ -11342,6 +13971,13 @@ var IrisTable = vue.defineComponent({
|
|
|
11342
13971
|
role: "columnheader",
|
|
11343
13972
|
"data-iris-table-header": col.key,
|
|
11344
13973
|
"data-iris-table-pinned": col.pinned,
|
|
13974
|
+
// Column drag-sort (vxe columnDragConfig parity, batch Y): the
|
|
13975
|
+
// header cell is the press target; grouped headers are NOT
|
|
13976
|
+
// supported (documented simplification — the reorder maps leaf
|
|
13977
|
+
// columns back to the parent, which a group column cannot do).
|
|
13978
|
+
"data-iris-col-drag-active": props.columnDrag && colDragState.value.activeId === col.key ? "true" : void 0,
|
|
13979
|
+
"data-iris-col-drag-over": props.columnDrag && colDragState.value.overId === col.key ? "true" : void 0,
|
|
13980
|
+
onPointerdown: props.columnDrag && !grouped.value ? (e) => handleColDragPointerDown(e, col.key) : void 0,
|
|
11345
13981
|
onClick: () => onHeaderClick(col),
|
|
11346
13982
|
style: {
|
|
11347
13983
|
position: "relative",
|
|
@@ -11362,9 +13998,16 @@ var IrisTable = vue.defineComponent({
|
|
|
11362
13998
|
...visibleColSet.value ? { gridColumnStart: String(colTrack(ci)) } : {},
|
|
11363
13999
|
...col.pinned ? { ...pinnedStyle(col.key), background: "var(--iris-surface)" } : {}
|
|
11364
14000
|
},
|
|
11365
|
-
"aria-sort":
|
|
14001
|
+
"aria-sort": ariaSortFor(col)
|
|
11366
14002
|
},
|
|
11367
|
-
[
|
|
14003
|
+
[
|
|
14004
|
+
title,
|
|
14005
|
+
sortIndicator(col),
|
|
14006
|
+
multiSortSeq(col),
|
|
14007
|
+
renderFilterTrigger(col, true),
|
|
14008
|
+
pinnedHandle,
|
|
14009
|
+
handle
|
|
14010
|
+
]
|
|
11368
14011
|
)
|
|
11369
14012
|
);
|
|
11370
14013
|
}
|
|
@@ -11384,6 +14027,69 @@ var IrisTable = vue.defineComponent({
|
|
|
11384
14027
|
const id = rowId(row, index);
|
|
11385
14028
|
const selected = isSelected(id);
|
|
11386
14029
|
const cells = [];
|
|
14030
|
+
if (showDrag) {
|
|
14031
|
+
const rowDragActive = rowDragState.value.activeId === String(id);
|
|
14032
|
+
const rowDragOver = rowDragState.value.overId === String(id);
|
|
14033
|
+
cells.push(
|
|
14034
|
+
vue.h(
|
|
14035
|
+
"div",
|
|
14036
|
+
{
|
|
14037
|
+
key: "__drag",
|
|
14038
|
+
role: "cell",
|
|
14039
|
+
"data-iris-table-cell": "__drag",
|
|
14040
|
+
// The drag handle carries the row's id as its attribute VALUE
|
|
14041
|
+
// (rect collection for closestCenter reads it back).
|
|
14042
|
+
"data-iris-row-drag-handle": String(id),
|
|
14043
|
+
"data-iris-row-drag-active": rowDragActive ? "true" : void 0,
|
|
14044
|
+
"data-iris-row-drag-over": rowDragOver ? "true" : void 0,
|
|
14045
|
+
onPointerdown: (e) => handleRowDragPointerDown(e, String(id)),
|
|
14046
|
+
onClick: (e) => e.stopPropagation(),
|
|
14047
|
+
style: {
|
|
14048
|
+
display: "flex",
|
|
14049
|
+
alignItems: "center",
|
|
14050
|
+
justifyContent: "center",
|
|
14051
|
+
padding: "8px 12px",
|
|
14052
|
+
borderBottom: "1px solid var(--iris-border)",
|
|
14053
|
+
cursor: "grab",
|
|
14054
|
+
color: "var(--iris-muted)",
|
|
14055
|
+
background: rowDragActive ? "var(--iris-surface-hover)" : rowDragOver ? "var(--iris-surface-selected, rgba(99,102,241,0.12))" : "transparent"
|
|
14056
|
+
}
|
|
14057
|
+
},
|
|
14058
|
+
[
|
|
14059
|
+
vue.h(
|
|
14060
|
+
"span",
|
|
14061
|
+
{
|
|
14062
|
+
"aria-hidden": "true",
|
|
14063
|
+
style: { fontSize: "var(--iris-font-size-sm, 13px)" }
|
|
14064
|
+
},
|
|
14065
|
+
"\u283F"
|
|
14066
|
+
)
|
|
14067
|
+
]
|
|
14068
|
+
)
|
|
14069
|
+
);
|
|
14070
|
+
}
|
|
14071
|
+
if (showSeq) {
|
|
14072
|
+
cells.push(
|
|
14073
|
+
vue.h(
|
|
14074
|
+
"div",
|
|
14075
|
+
{
|
|
14076
|
+
key: "__seq",
|
|
14077
|
+
role: "cell",
|
|
14078
|
+
"data-iris-table-cell": "__seq",
|
|
14079
|
+
style: {
|
|
14080
|
+
display: "flex",
|
|
14081
|
+
alignItems: "center",
|
|
14082
|
+
justifyContent: "center",
|
|
14083
|
+
padding: "8px 12px",
|
|
14084
|
+
borderBottom: "1px solid var(--iris-border)",
|
|
14085
|
+
color: "var(--iris-muted)",
|
|
14086
|
+
userSelect: "none"
|
|
14087
|
+
}
|
|
14088
|
+
},
|
|
14089
|
+
String(index + props.seqStartIndex)
|
|
14090
|
+
)
|
|
14091
|
+
);
|
|
14092
|
+
}
|
|
11387
14093
|
if (showDetail) {
|
|
11388
14094
|
const rowExpandable = isRowExpandable(row, index);
|
|
11389
14095
|
const isExpanded = expandedKeys.value.includes(String(id));
|
|
@@ -11460,115 +14166,30 @@ var IrisTable = vue.defineComponent({
|
|
|
11460
14166
|
for (let ci = 0; ci < leafColumns.value.length; ci += 1) {
|
|
11461
14167
|
const col = leafColumns.value[ci];
|
|
11462
14168
|
if (visibleColSet.value && !visibleColSet.value.has(ci)) continue;
|
|
14169
|
+
const span = resolveSpan(spanOccupy, index, ci, props.spanMethod);
|
|
14170
|
+
if (span === null) continue;
|
|
14171
|
+
const rowspan = span.rowspan;
|
|
14172
|
+
const colspan = span.colspan;
|
|
11463
14173
|
const align = col.align ?? "left";
|
|
11464
14174
|
const cellSlot = slots[`cell.${col.key}`];
|
|
11465
|
-
const
|
|
14175
|
+
const isRowEditing = rowMode.value && rowEditing.value !== null && rowEditing.value.k === id && rowSessions.value.has(cellId(id, col.key));
|
|
14176
|
+
const isEditing = isRowEditing || editingCellId.value === cellId(id, col.key);
|
|
14177
|
+
const patternHint = (props.pattern || props.patternFill) && !rowMode.value && editingColumnKey.value === col.key && !isEditing && editingDraft.value !== "" && String(getCellValue(row, col) ?? "") === editingDraft.value;
|
|
11466
14178
|
let content;
|
|
11467
14179
|
if (isEditing) {
|
|
11468
14180
|
const editCellId = cellId(id, col.key);
|
|
11469
|
-
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
value
|
|
11476
|
-
|
|
11477
|
-
"aria-invalid": error ? "true" : void 0,
|
|
11478
|
-
"aria-describedby": error ? `${editCellId}-error` : void 0,
|
|
11479
|
-
onInput: (e) => {
|
|
11480
|
-
editingDraft.value = e.target.value;
|
|
11481
|
-
},
|
|
11482
|
-
onKeydown: (e) => {
|
|
11483
|
-
if (e.key === "Enter") {
|
|
11484
|
-
e.preventDefault();
|
|
11485
|
-
commitEdit(row, col, index);
|
|
11486
|
-
} else if (e.key === "Escape") {
|
|
11487
|
-
e.preventDefault();
|
|
11488
|
-
cancelEdit();
|
|
11489
|
-
}
|
|
11490
|
-
},
|
|
11491
|
-
onBlur: () => commitEdit(row, col, index),
|
|
11492
|
-
onClick: (e) => e.stopPropagation(),
|
|
11493
|
-
onDblclick: (e) => e.stopPropagation(),
|
|
11494
|
-
style: {
|
|
11495
|
-
width: "100%",
|
|
11496
|
-
border: `1px solid ${error ? "var(--iris-danger)" : "var(--iris-primary)"}`,
|
|
11497
|
-
borderRadius: "var(--iris-radius-sm)",
|
|
11498
|
-
padding: "var(--iris-space-xxs, 4px) var(--iris-padding-sm, 6px)",
|
|
11499
|
-
font: "inherit",
|
|
11500
|
-
background: "var(--iris-background)",
|
|
11501
|
-
color: "var(--iris-foreground)",
|
|
11502
|
-
outline: "none",
|
|
11503
|
-
boxShadow: "0 0 0 3px color-mix(in srgb, var(--iris-primary) 18%, transparent)"
|
|
11504
|
-
}
|
|
11505
|
-
});
|
|
11506
|
-
content = error ? [
|
|
11507
|
-
input,
|
|
11508
|
-
vue.h(
|
|
11509
|
-
"div",
|
|
11510
|
-
{
|
|
11511
|
-
id: `${editCellId}-error`,
|
|
11512
|
-
role: "alert",
|
|
11513
|
-
"data-iris-table-editor-error": "",
|
|
11514
|
-
style: {
|
|
11515
|
-
marginTop: "var(--iris-space-xxs, 4px)",
|
|
11516
|
-
fontSize: "var(--iris-font-size-xs, 12px)",
|
|
11517
|
-
color: "var(--iris-danger)"
|
|
11518
|
-
}
|
|
11519
|
-
},
|
|
11520
|
-
error
|
|
11521
|
-
)
|
|
11522
|
-
] : input;
|
|
14181
|
+
content = isRowEditing ? buildRowSessionContent(
|
|
14182
|
+
row,
|
|
14183
|
+
col,
|
|
14184
|
+
index,
|
|
14185
|
+
id,
|
|
14186
|
+
editCellId,
|
|
14187
|
+
rowSessions.value.get(editCellId)
|
|
14188
|
+
) : buildCellEditContent(row, col, index, editCellId);
|
|
11523
14189
|
} else {
|
|
11524
|
-
content = cellSlot?.({ row, index, value:
|
|
14190
|
+
content = cellSlot?.({ row, index, value: getCellValue(row, col) }) ?? core.tableDisplayText(row, col);
|
|
11525
14191
|
}
|
|
11526
|
-
const treeIndent = treeMeta && ci === 0 ?
|
|
11527
|
-
"span",
|
|
11528
|
-
{
|
|
11529
|
-
"data-iris-table-tree-indent": "",
|
|
11530
|
-
style: {
|
|
11531
|
-
display: "inline-flex",
|
|
11532
|
-
alignItems: "center",
|
|
11533
|
-
flex: "none",
|
|
11534
|
-
paddingLeft: `${treeMeta.depth * 16}px`
|
|
11535
|
-
}
|
|
11536
|
-
},
|
|
11537
|
-
treeMeta.hasChildren ? [
|
|
11538
|
-
vue.h(
|
|
11539
|
-
"button",
|
|
11540
|
-
{
|
|
11541
|
-
type: "button",
|
|
11542
|
-
"data-iris-table-tree-toggle": "",
|
|
11543
|
-
"aria-expanded": treeMeta.expanded ? "true" : "false",
|
|
11544
|
-
"aria-label": t(
|
|
11545
|
-
treeMeta.expanded ? "treeSelect.collapse" : "treeSelect.expand"
|
|
11546
|
-
),
|
|
11547
|
-
onClick: (e) => {
|
|
11548
|
-
e.stopPropagation();
|
|
11549
|
-
expansion.toggle(treeMeta.key);
|
|
11550
|
-
},
|
|
11551
|
-
style: {
|
|
11552
|
-
border: "none",
|
|
11553
|
-
background: "transparent",
|
|
11554
|
-
cursor: "pointer",
|
|
11555
|
-
padding: "0",
|
|
11556
|
-
marginRight: "4px",
|
|
11557
|
-
font: "inherit",
|
|
11558
|
-
color: "var(--iris-foreground)",
|
|
11559
|
-
transform: treeMeta.expanded ? "rotate(90deg)" : "none",
|
|
11560
|
-
transition: "transform 150ms"
|
|
11561
|
-
}
|
|
11562
|
-
},
|
|
11563
|
-
"\u25B6"
|
|
11564
|
-
)
|
|
11565
|
-
] : [
|
|
11566
|
-
vue.h("span", {
|
|
11567
|
-
"aria-hidden": "true",
|
|
11568
|
-
style: { display: "inline-block", width: "16px" }
|
|
11569
|
-
})
|
|
11570
|
-
]
|
|
11571
|
-
) : null;
|
|
14192
|
+
const treeIndent = treeMeta && ci === 0 ? buildTreeIndent(treeMeta, row) : null;
|
|
11572
14193
|
const cellChildren = treeIndent ? [treeIndent, ...Array.isArray(content) ? content : [content]] : content;
|
|
11573
14194
|
cells.push(
|
|
11574
14195
|
vue.h(
|
|
@@ -11580,6 +14201,7 @@ var IrisTable = vue.defineComponent({
|
|
|
11580
14201
|
"data-iris-table-pinned": col.pinned,
|
|
11581
14202
|
"data-editable": col.editable ? "" : void 0,
|
|
11582
14203
|
"data-editing": isEditing ? "" : void 0,
|
|
14204
|
+
"data-iris-input-hint": patternHint ? "true" : void 0,
|
|
11583
14205
|
// Grid keyboard navigation (opt-in): grid coords + roving tabindex
|
|
11584
14206
|
// (exactly one cell is 0) + an onFocus that syncs the focused cell.
|
|
11585
14207
|
...props.keyboardNavigation ? {
|
|
@@ -11603,14 +14225,19 @@ var IrisTable = vue.defineComponent({
|
|
|
11603
14225
|
}
|
|
11604
14226
|
}
|
|
11605
14227
|
} : {},
|
|
11606
|
-
onDblclick: col.editable ? () => beginEdit(row, col, id) : void 0,
|
|
11607
|
-
onClick:
|
|
14228
|
+
onDblclick: rowMode.value ? () => switchRowEdit(row, index, col.key) : col.editable ? () => beginEdit(row, col, id) : void 0,
|
|
14229
|
+
onClick: rowMode.value ? () => handleRowModeCellClick(row, col, index, id) : props.cellRange ? (e) => {
|
|
14230
|
+
if (e.shiftKey) cellRangeCtrl.extendRange(index, ci);
|
|
14231
|
+
else cellRangeCtrl.startRange(index, ci);
|
|
14232
|
+
} : col.editable && props.editConfig?.trigger === "click" ? () => beginEdit(row, col, id) : void 0,
|
|
14233
|
+
onContextmenu: props.contextMenu ? (e) => handleContextMenu(e, row, col, index, ci) : void 0,
|
|
11608
14234
|
style: {
|
|
11609
14235
|
display: "flex",
|
|
11610
14236
|
alignItems: "center",
|
|
11611
14237
|
justifyContent: align === "right" ? "flex-end" : align === "center" ? "center" : "flex-start",
|
|
11612
14238
|
background: "var(--iris-cell-bg, transparent)",
|
|
11613
14239
|
padding: isEditing ? "var(--iris-space-xxs, 4px)" : "var(--iris-space-xs, 8px) var(--iris-padding-md)",
|
|
14240
|
+
...isEditing ? { flexWrap: "wrap" } : {},
|
|
11614
14241
|
borderBottom: "1px solid var(--iris-border)",
|
|
11615
14242
|
fontSize: "var(--iris-font-size-md, 14px)",
|
|
11616
14243
|
whiteSpace: "nowrap",
|
|
@@ -11619,6 +14246,11 @@ var IrisTable = vue.defineComponent({
|
|
|
11619
14246
|
cursor: col.editable ? "cell" : "default",
|
|
11620
14247
|
...props.cellRange && isInRange(index, ci) ? { background: "var(--iris-surface-selected, rgba(99,102,241,0.12))" } : {},
|
|
11621
14248
|
...visibleColSet.value ? { gridColumnStart: String(colTrack(ci)) } : {},
|
|
14249
|
+
...colspan > 1 ? { gridColumnEnd: `span ${colspan}` } : {},
|
|
14250
|
+
...rowspan > 1 ? { gridRowEnd: `span ${rowspan}` } : {},
|
|
14251
|
+
...patternHint ? {
|
|
14252
|
+
backgroundImage: "linear-gradient(var(--iris-input-hint, rgba(251, 191, 36, 0.16)), var(--iris-input-hint, rgba(251, 191, 36, 0.16)))"
|
|
14253
|
+
} : {},
|
|
11622
14254
|
...pinnedStyle(col.key)
|
|
11623
14255
|
}
|
|
11624
14256
|
},
|
|
@@ -11640,6 +14272,8 @@ var IrisTable = vue.defineComponent({
|
|
|
11640
14272
|
"aria-setsize": treeMeta ? treeMeta.setSize : void 0,
|
|
11641
14273
|
"aria-posinset": treeMeta ? treeMeta.posInset : void 0,
|
|
11642
14274
|
"data-iris-table-row": "",
|
|
14275
|
+
"data-iris-table-row-key": String(id),
|
|
14276
|
+
"data-iris-row-editing": rowMode.value && rowEditing.value?.k === id ? "true" : void 0,
|
|
11643
14277
|
"data-state": selected ? "selected" : void 0,
|
|
11644
14278
|
onClick: () => emit("rowClick", row, index),
|
|
11645
14279
|
onDblclick: () => emit("rowDblclick", row, index),
|
|
@@ -11660,50 +14294,21 @@ var IrisTable = vue.defineComponent({
|
|
|
11660
14294
|
textAlign: "center",
|
|
11661
14295
|
color: "var(--iris-muted)"
|
|
11662
14296
|
};
|
|
14297
|
+
const stateNode = renderTableStateRow({
|
|
14298
|
+
error: tableError.value,
|
|
14299
|
+
loading: tableLoading.value,
|
|
14300
|
+
rowCount: bodyData.value.length,
|
|
14301
|
+
stateRowStyle,
|
|
14302
|
+
errorContent: slots.error ? slots.error() : t("table.error"),
|
|
14303
|
+
loadingContent: slots.loading ? slots.loading() : t("table.loading"),
|
|
14304
|
+
emptyContent: slots.empty ? slots.empty() : t("table.empty"),
|
|
14305
|
+
retry: retry.value,
|
|
14306
|
+
onRetry: props.onRetry,
|
|
14307
|
+
retryLabel: t("table.retry")
|
|
14308
|
+
});
|
|
11663
14309
|
let bodyNode;
|
|
11664
|
-
if (
|
|
11665
|
-
bodyNode =
|
|
11666
|
-
vue.h(
|
|
11667
|
-
"span",
|
|
11668
|
-
{ style: { marginInlineEnd: props.onRetry ? "var(--iris-space-sm, 12px)" : "0px" } },
|
|
11669
|
-
slots.error ? slots.error() : t("table.error")
|
|
11670
|
-
),
|
|
11671
|
-
props.onRetry ? vue.h(
|
|
11672
|
-
"button",
|
|
11673
|
-
{
|
|
11674
|
-
type: "button",
|
|
11675
|
-
"data-iris-table-retry": "",
|
|
11676
|
-
onClick: props.onRetry,
|
|
11677
|
-
style: {
|
|
11678
|
-
border: "1px solid var(--iris-border)",
|
|
11679
|
-
background: "var(--iris-surface)",
|
|
11680
|
-
color: "var(--iris-foreground)",
|
|
11681
|
-
borderRadius: "var(--iris-radius-sm, 4px)",
|
|
11682
|
-
padding: "var(--iris-space-xxs, 4px) var(--iris-space-xs, 8px)",
|
|
11683
|
-
fontSize: "var(--iris-font-size-sm, 13px)",
|
|
11684
|
-
cursor: "pointer"
|
|
11685
|
-
}
|
|
11686
|
-
},
|
|
11687
|
-
t("table.retry")
|
|
11688
|
-
) : null
|
|
11689
|
-
]);
|
|
11690
|
-
} else if (props.loading) {
|
|
11691
|
-
bodyNode = vue.h(
|
|
11692
|
-
"div",
|
|
11693
|
-
{
|
|
11694
|
-
role: "row",
|
|
11695
|
-
"aria-busy": "true",
|
|
11696
|
-
"data-iris-table-row": "loading",
|
|
11697
|
-
style: stateRowStyle
|
|
11698
|
-
},
|
|
11699
|
-
slots.loading ? slots.loading() : t("table.loading")
|
|
11700
|
-
);
|
|
11701
|
-
} else if (bodyData.value.length === 0) {
|
|
11702
|
-
bodyNode = vue.h(
|
|
11703
|
-
"div",
|
|
11704
|
-
{ role: "row", "data-iris-table-row": "empty", style: stateRowStyle },
|
|
11705
|
-
slots.empty ? slots.empty() : t("table.empty")
|
|
11706
|
-
);
|
|
14310
|
+
if (stateNode) {
|
|
14311
|
+
bodyNode = stateNode;
|
|
11707
14312
|
} else if (props.virtualScroll && (!treeMode.value || !hasDetail.value)) {
|
|
11708
14313
|
bodyNode = vue.h(
|
|
11709
14314
|
IrisVirtualScroll,
|
|
@@ -11767,127 +14372,105 @@ var IrisTable = vue.defineComponent({
|
|
|
11767
14372
|
bodyChildren
|
|
11768
14373
|
);
|
|
11769
14374
|
}
|
|
11770
|
-
|
|
11771
|
-
|
|
11772
|
-
|
|
11773
|
-
|
|
11774
|
-
|
|
11775
|
-
|
|
11776
|
-
|
|
11777
|
-
|
|
11778
|
-
|
|
11779
|
-
|
|
11780
|
-
|
|
11781
|
-
|
|
11782
|
-
|
|
11783
|
-
|
|
11784
|
-
|
|
11785
|
-
|
|
11786
|
-
|
|
11787
|
-
|
|
11788
|
-
|
|
11789
|
-
|
|
11790
|
-
|
|
11791
|
-
|
|
11792
|
-
|
|
11793
|
-
|
|
11794
|
-
|
|
11795
|
-
|
|
11796
|
-
|
|
11797
|
-
"div",
|
|
11798
|
-
{
|
|
11799
|
-
key: col.key,
|
|
11800
|
-
role: "cell",
|
|
11801
|
-
"data-iris-table-cell": col.key,
|
|
11802
|
-
"data-iris-table-summary-cell": op ? "" : void 0,
|
|
11803
|
-
"data-iris-table-pinned": col.pinned,
|
|
11804
|
-
style: {
|
|
11805
|
-
display: "flex",
|
|
11806
|
-
alignItems: "center",
|
|
11807
|
-
justifyContent: align === "right" ? "flex-end" : align === "center" ? "center" : "flex-start",
|
|
11808
|
-
padding: "var(--iris-space-xs, 8px) var(--iris-padding-md)",
|
|
11809
|
-
fontSize: "var(--iris-font-size-md, 14px)",
|
|
11810
|
-
whiteSpace: "nowrap",
|
|
11811
|
-
overflow: "hidden",
|
|
11812
|
-
textOverflow: "ellipsis",
|
|
11813
|
-
...visibleColSet.value ? { gridColumnStart: String(colTrack(ci)) } : {},
|
|
11814
|
-
...pinnedStyle(col.key)
|
|
11815
|
-
}
|
|
11816
|
-
},
|
|
11817
|
-
summaryContent
|
|
11818
|
-
)
|
|
11819
|
-
);
|
|
11820
|
-
}
|
|
11821
|
-
summaryRow = vue.h(
|
|
14375
|
+
const summaryRow = !tableError.value && !tableLoading.value ? renderTableSummaryRow({
|
|
14376
|
+
bodyData: bodyData.value,
|
|
14377
|
+
leafColumns: leafColumns.value,
|
|
14378
|
+
visibleColSet: visibleColSet.value,
|
|
14379
|
+
gridTemplate: gridTemplate.value,
|
|
14380
|
+
leadingCells: leadSummaryCells(),
|
|
14381
|
+
colTrack,
|
|
14382
|
+
getCellValue,
|
|
14383
|
+
pinnedStyle
|
|
14384
|
+
}) : null;
|
|
14385
|
+
const rootNodes = [
|
|
14386
|
+
tableViews.renderTabs(props.tableTabs),
|
|
14387
|
+
tableViews.renderViews(),
|
|
14388
|
+
buildFormSection(),
|
|
14389
|
+
buildToolbarSection(),
|
|
14390
|
+
props.clipConfig && props.clipConfig.copy !== false && activeCellRange() ? vue.h(
|
|
14391
|
+
"button",
|
|
14392
|
+
{ type: "button", "data-iris-table-range-copy": "", onClick: copyActiveRange },
|
|
14393
|
+
t("table.range.copy")
|
|
14394
|
+
) : null,
|
|
14395
|
+
renderImportPreviewSection({
|
|
14396
|
+
rows: importController.importPreviewRows.value,
|
|
14397
|
+
t,
|
|
14398
|
+
onConfirm: importController.confirmImportPreview,
|
|
14399
|
+
onCancel: importController.cancelImportPreview
|
|
14400
|
+
}),
|
|
14401
|
+
vue.h(
|
|
11822
14402
|
"div",
|
|
11823
14403
|
{
|
|
11824
|
-
|
|
11825
|
-
|
|
14404
|
+
...attrs,
|
|
14405
|
+
ref: (el) => {
|
|
14406
|
+
rootRef.value = el ?? null;
|
|
14407
|
+
},
|
|
14408
|
+
// A keyboard-navigable hierarchical table is a `treegrid`; otherwise the
|
|
14409
|
+
// grid/table role as before (treegrid implies managed cell focus).
|
|
14410
|
+
role: props.keyboardNavigation ? treeMode.value ? "treegrid" : "grid" : "table",
|
|
14411
|
+
"data-iris-table": "",
|
|
14412
|
+
"data-density": effectiveDensity.value,
|
|
14413
|
+
"data-printable": props.printable ? "true" : void 0,
|
|
14414
|
+
"data-virtual": props.virtualScroll ? "" : void 0,
|
|
14415
|
+
"data-column-virtualized": props.columnVirtualization ? "true" : void 0,
|
|
14416
|
+
onKeydown: props.keyboardNavigation || props.cellRange || props.clipConfig ? (e) => handleRootKeyDown(e) : void 0,
|
|
14417
|
+
onScroll: props.columnVirtualization ? (e) => {
|
|
14418
|
+
scrollLeft.value = e.currentTarget.scrollLeft;
|
|
14419
|
+
} : void 0,
|
|
14420
|
+
// Row/column drag-sort (batch Y): container-level pointer handling
|
|
14421
|
+
// for both reorders (React parity) — press happens on the row
|
|
14422
|
+
// handle / header cell, move/up resolve at the container.
|
|
14423
|
+
onPointermove: props.rowDrag || props.columnDrag ? (e) => {
|
|
14424
|
+
handleRowDragPointerMove(e);
|
|
14425
|
+
handleColDragPointerMove(e);
|
|
14426
|
+
} : void 0,
|
|
14427
|
+
onPointerup: props.rowDrag || props.columnDrag ? () => {
|
|
14428
|
+
handleRowDragPointerUp();
|
|
14429
|
+
handleColDragPointerUp();
|
|
14430
|
+
} : void 0,
|
|
14431
|
+
onPointerleave: props.rowDrag ? handleRowDragPointerLeave : void 0,
|
|
11826
14432
|
style: {
|
|
11827
|
-
|
|
11828
|
-
|
|
11829
|
-
|
|
11830
|
-
|
|
11831
|
-
|
|
14433
|
+
background: "var(--iris-background)",
|
|
14434
|
+
color: "var(--iris-foreground)",
|
|
14435
|
+
fontSize: "var(--iris-font-size-md, 14px)",
|
|
14436
|
+
border: props.bordered ? "1px solid var(--iris-border)" : "none",
|
|
14437
|
+
borderRadius: "var(--iris-radius-md)",
|
|
14438
|
+
// Column virtualization and responsive overflow turn the table
|
|
14439
|
+
// into a horizontal scroll container.
|
|
14440
|
+
overflow: props.columnVirtualization || responsiveOverflow.value ? "auto" : "hidden",
|
|
14441
|
+
...responsiveOverflow.value ? { overflowX: "auto" } : {},
|
|
14442
|
+
...attrs.style ?? {}
|
|
11832
14443
|
}
|
|
11833
14444
|
},
|
|
11834
|
-
|
|
11835
|
-
)
|
|
11836
|
-
|
|
11837
|
-
|
|
11838
|
-
|
|
11839
|
-
|
|
11840
|
-
|
|
11841
|
-
|
|
11842
|
-
|
|
14445
|
+
[headerRow, bodyNode, summaryRow, buildPagerSection()]
|
|
14446
|
+
),
|
|
14447
|
+
props.responsive && responsiveOverflow.value && !props.printable ? vue.h(
|
|
14448
|
+
"div",
|
|
14449
|
+
{
|
|
14450
|
+
"data-iris-scroll-hint": "",
|
|
14451
|
+
role: "status",
|
|
14452
|
+
"aria-live": "polite",
|
|
14453
|
+
style: {
|
|
14454
|
+
display: "flex",
|
|
14455
|
+
alignItems: "center",
|
|
14456
|
+
gap: "var(--iris-space-xxs, 4px)",
|
|
14457
|
+
padding: "var(--iris-space-xxs, 4px) var(--iris-space-sm, 12px)",
|
|
14458
|
+
color: "var(--iris-muted)",
|
|
14459
|
+
background: "var(--iris-surface)",
|
|
14460
|
+
borderInline: "1px solid var(--iris-border)",
|
|
14461
|
+
borderBottom: "1px solid var(--iris-border)",
|
|
14462
|
+
fontSize: "var(--iris-font-size-sm, 13px)"
|
|
14463
|
+
}
|
|
11843
14464
|
},
|
|
11844
|
-
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
onKeydown: props.keyboardNavigation || props.cellRange ? (e) => {
|
|
11851
|
-
if (props.keyboardNavigation) handleGridKey(e);
|
|
11852
|
-
if (props.cellRange) handleCellRangeKey(e);
|
|
11853
|
-
} : void 0,
|
|
11854
|
-
onScroll: props.columnVirtualization ? (e) => {
|
|
11855
|
-
scrollLeft.value = e.currentTarget.scrollLeft;
|
|
11856
|
-
} : void 0,
|
|
11857
|
-
style: {
|
|
11858
|
-
background: "var(--iris-background)",
|
|
11859
|
-
color: "var(--iris-foreground)",
|
|
11860
|
-
fontSize: "var(--iris-font-size-md, 14px)",
|
|
11861
|
-
border: props.bordered ? "1px solid var(--iris-border)" : "none",
|
|
11862
|
-
borderRadius: "var(--iris-radius-md)",
|
|
11863
|
-
// Column virtualization turns the table into a horizontal scroll container.
|
|
11864
|
-
overflow: props.columnVirtualization ? "auto" : "hidden",
|
|
11865
|
-
...attrs.style ?? {}
|
|
11866
|
-
}
|
|
11867
|
-
},
|
|
11868
|
-
[headerRow, bodyNode, summaryRow]
|
|
11869
|
-
);
|
|
14465
|
+
[vue.h("span", { "aria-hidden": "true" }, "\u21C6"), vue.h("span", t("table.scrollHint"))]
|
|
14466
|
+
) : null,
|
|
14467
|
+
buildContextMenuSection(),
|
|
14468
|
+
buildFilterPanelSection()
|
|
14469
|
+
].filter((n) => n !== null);
|
|
14470
|
+
return rootNodes.length === 1 ? rootNodes[0] : rootNodes;
|
|
11870
14471
|
};
|
|
11871
14472
|
}
|
|
11872
14473
|
});
|
|
11873
|
-
function exportCsv(rows, columns) {
|
|
11874
|
-
return core.toCsv(
|
|
11875
|
-
rows,
|
|
11876
|
-
columns.map((column) => ({
|
|
11877
|
-
key: column.key,
|
|
11878
|
-
title: column.title,
|
|
11879
|
-
dataIndex: typeof column.dataIndex === "string" ? column.dataIndex : void 0
|
|
11880
|
-
}))
|
|
11881
|
-
);
|
|
11882
|
-
}
|
|
11883
|
-
async function downloadCsv(filename, csv) {
|
|
11884
|
-
const BOM = String.fromCharCode(65279);
|
|
11885
|
-
await core.downloadFile({
|
|
11886
|
-
filename,
|
|
11887
|
-
content: BOM + csv,
|
|
11888
|
-
mimeType: "text/csv;charset=utf-8;"
|
|
11889
|
-
});
|
|
11890
|
-
}
|
|
11891
14474
|
function exportExcel(rows, columns, options) {
|
|
11892
14475
|
return core.toSpreadsheetXml(
|
|
11893
14476
|
rows,
|
|
@@ -11908,7 +14491,7 @@ async function downloadExcel(filename, xml) {
|
|
|
11908
14491
|
}
|
|
11909
14492
|
|
|
11910
14493
|
// src/primitives/tabs/context.ts
|
|
11911
|
-
var TabsContextKey =
|
|
14494
|
+
var TabsContextKey = Symbol("IrisTabs");
|
|
11912
14495
|
|
|
11913
14496
|
// src/primitives/tabs/Tabs.ts
|
|
11914
14497
|
var IrisTabs = vue.defineComponent({
|
|
@@ -12208,7 +14791,7 @@ var IrisTabsContent = vue.defineComponent({
|
|
|
12208
14791
|
});
|
|
12209
14792
|
|
|
12210
14793
|
// src/primitives/menu/context.ts
|
|
12211
|
-
var MenuContextKey =
|
|
14794
|
+
var MenuContextKey = Symbol("IrisMenu");
|
|
12212
14795
|
|
|
12213
14796
|
// src/primitives/menu/Menu.ts
|
|
12214
14797
|
var IrisMenu = vue.defineComponent({
|
|
@@ -13055,6 +15638,29 @@ var TREE_STATE_STYLE = {
|
|
|
13055
15638
|
color: "var(--iris-muted)",
|
|
13056
15639
|
fontSize: "var(--iris-font-size-md, 14px)"
|
|
13057
15640
|
};
|
|
15641
|
+
function renderTreeState({
|
|
15642
|
+
state,
|
|
15643
|
+
stateKey,
|
|
15644
|
+
stateProps,
|
|
15645
|
+
slots,
|
|
15646
|
+
translate
|
|
15647
|
+
}) {
|
|
15648
|
+
const content = state === "error" ? slots.error ? slots.error() : translate("tree.error") : state === "loading" ? slots.loading ? slots.loading() : translate("tree.loading") : slots.empty ? slots.empty() : translate("tree.empty");
|
|
15649
|
+
return vue.h(
|
|
15650
|
+
"div",
|
|
15651
|
+
{
|
|
15652
|
+
key: stateKey,
|
|
15653
|
+
role: "presentation",
|
|
15654
|
+
"data-iris-tree-state": state,
|
|
15655
|
+
"aria-live": "polite",
|
|
15656
|
+
...stateProps,
|
|
15657
|
+
style: TREE_STATE_STYLE
|
|
15658
|
+
},
|
|
15659
|
+
content
|
|
15660
|
+
);
|
|
15661
|
+
}
|
|
15662
|
+
|
|
15663
|
+
// src/primitives/tree/Tree.ts
|
|
13058
15664
|
var IrisTree = vue.defineComponent({
|
|
13059
15665
|
name: "IrisTree",
|
|
13060
15666
|
inheritAttrs: false,
|
|
@@ -13284,21 +15890,6 @@ var IrisTree = vue.defineComponent({
|
|
|
13284
15890
|
break;
|
|
13285
15891
|
}
|
|
13286
15892
|
}
|
|
13287
|
-
const renderStateNode = () => {
|
|
13288
|
-
const content = state.value === "error" ? slots.error ? slots.error() : t("tree.error") : state.value === "loading" ? slots.loading ? slots.loading() : t("tree.loading") : slots.empty ? slots.empty() : t("tree.empty");
|
|
13289
|
-
return vue.h(
|
|
13290
|
-
"div",
|
|
13291
|
-
{
|
|
13292
|
-
key: stateKey.value,
|
|
13293
|
-
role: "presentation",
|
|
13294
|
-
"data-iris-tree-state": state.value,
|
|
13295
|
-
"aria-live": "polite",
|
|
13296
|
-
...stateProps.value,
|
|
13297
|
-
style: TREE_STATE_STYLE
|
|
13298
|
-
},
|
|
13299
|
-
content
|
|
13300
|
-
);
|
|
13301
|
-
};
|
|
13302
15893
|
const renderItems = () => {
|
|
13303
15894
|
void checkedKeys.value;
|
|
13304
15895
|
return flat.value.map((entry) => {
|
|
@@ -13431,7 +16022,15 @@ var IrisTree = vue.defineComponent({
|
|
|
13431
16022
|
...attrs.style ?? {}
|
|
13432
16023
|
}
|
|
13433
16024
|
},
|
|
13434
|
-
isContent.value ? renderItems() : [
|
|
16025
|
+
isContent.value ? renderItems() : [
|
|
16026
|
+
renderTreeState({
|
|
16027
|
+
state: state.value,
|
|
16028
|
+
stateKey: stateKey.value,
|
|
16029
|
+
stateProps: stateProps.value,
|
|
16030
|
+
slots,
|
|
16031
|
+
translate: t
|
|
16032
|
+
})
|
|
16033
|
+
]
|
|
13435
16034
|
);
|
|
13436
16035
|
}
|
|
13437
16036
|
});
|
|
@@ -18664,12 +21263,12 @@ function defaultFilter(query, item) {
|
|
|
18664
21263
|
if (!q) return 0;
|
|
18665
21264
|
const haystacks = [item.label, ...item.keywords ?? []].map((s) => s.toLowerCase());
|
|
18666
21265
|
let best = null;
|
|
18667
|
-
for (const
|
|
21266
|
+
for (const h136 of haystacks) {
|
|
18668
21267
|
let qi = 0;
|
|
18669
21268
|
let lastIdx = -1;
|
|
18670
21269
|
let score = 0;
|
|
18671
|
-
for (let i = 0; i <
|
|
18672
|
-
if (
|
|
21270
|
+
for (let i = 0; i < h136.length && qi < q.length; i += 1) {
|
|
21271
|
+
if (h136[i] === q[qi]) {
|
|
18673
21272
|
score += lastIdx === -1 ? i : i - lastIdx - 1;
|
|
18674
21273
|
lastIdx = i;
|
|
18675
21274
|
qi += 1;
|
|
@@ -19035,8 +21634,8 @@ var IrisTimePicker = vue.defineComponent({
|
|
|
19035
21634
|
if (props.format === "24h") {
|
|
19036
21635
|
return { h: value.value.hours, m: value.value.minutes };
|
|
19037
21636
|
}
|
|
19038
|
-
const
|
|
19039
|
-
return { h:
|
|
21637
|
+
const h1210 = value.value.hours % 12 === 0 ? 12 : value.value.hours % 12;
|
|
21638
|
+
return { h: h1210, m: value.value.minutes };
|
|
19040
21639
|
});
|
|
19041
21640
|
const emitNew = (next) => {
|
|
19042
21641
|
emit("update:modelValue", next);
|
|
@@ -19052,16 +21651,16 @@ var IrisTimePicker = vue.defineComponent({
|
|
|
19052
21651
|
};
|
|
19053
21652
|
const toggleMeridiem = () => {
|
|
19054
21653
|
const isPM = meridiem.value === "PM";
|
|
19055
|
-
const
|
|
19056
|
-
const newH24 = isPM ?
|
|
21654
|
+
const h1210 = value.value.hours % 12;
|
|
21655
|
+
const newH24 = isPM ? h1210 : h1210 + 12;
|
|
19057
21656
|
emitNew({ hours: newH24, minutes: value.value.minutes });
|
|
19058
21657
|
};
|
|
19059
21658
|
const onHoursInput = (e) => {
|
|
19060
21659
|
const v = parseInt(e.target.value || "0", 10);
|
|
19061
21660
|
if (Number.isNaN(v)) return;
|
|
19062
21661
|
if (props.format === "12h") {
|
|
19063
|
-
const
|
|
19064
|
-
const wrap =
|
|
21662
|
+
const h1210 = clamp5(v, 1, 12);
|
|
21663
|
+
const wrap = h1210 === 12 ? 0 : h1210;
|
|
19065
21664
|
const newH24 = meridiem.value === "PM" ? wrap + 12 : wrap;
|
|
19066
21665
|
setHours24(newH24);
|
|
19067
21666
|
} else {
|
|
@@ -20582,6 +23181,10 @@ Object.defineProperty(exports, "nodeAllowsRoles", {
|
|
|
20582
23181
|
enumerable: true,
|
|
20583
23182
|
get: function () { return core.nodeAllowsRoles; }
|
|
20584
23183
|
});
|
|
23184
|
+
Object.defineProperty(exports, "parseCsv", {
|
|
23185
|
+
enumerable: true,
|
|
23186
|
+
get: function () { return core.parseCsv; }
|
|
23187
|
+
});
|
|
20585
23188
|
Object.defineProperty(exports, "rgbToHex", {
|
|
20586
23189
|
enumerable: true,
|
|
20587
23190
|
get: function () { return core.rgbToHex; }
|