@xleddyl/443-components-vue 0.8.2 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -18
- package/dist/components/core/FormField.vue +5 -0
- package/dist/components/core/FormField.vue.d.ts +4 -0
- package/dist/components/core/Input.vue +59 -5
- package/dist/components/core/Input.vue.d.ts +8 -4
- package/dist/components/core/Textarea.vue +28 -3
- package/dist/components/core/Textarea.vue.d.ts +6 -4
- package/dist/components/data/DescriptionList.vue.d.ts +1 -1
- package/dist/components/data/Pagination.vue +8 -2
- package/dist/components/data/Pagination.vue.d.ts +2 -0
- package/dist/components/forms/CheckboxGroup.vue +7 -1
- package/dist/components/forms/CheckboxGroup.vue.d.ts +1 -0
- package/dist/components/forms/ColorInput.vue.d.ts +4 -4
- package/dist/components/forms/Combobox.vue +4 -3
- package/dist/components/forms/Combobox.vue.d.ts +1 -0
- package/dist/components/forms/DateInput.vue.d.ts +8 -4
- package/dist/components/forms/NumberInput.vue.d.ts +4 -4
- package/dist/components/forms/PasswordInput.vue.d.ts +8 -4
- package/dist/components/forms/PinInput.vue.d.ts +4 -4
- package/dist/components/forms/Select.vue +21 -2
- package/dist/components/forms/Select.vue.d.ts +3 -3
- package/dist/components/forms/Slider.vue.d.ts +4 -4
- package/dist/components/forms/TimeInput.vue.d.ts +8 -4
- package/dist/components/layout/Card.vue.d.ts +1 -1
- package/dist/components/overlays/ConfirmDialog.vue.d.ts +2 -2
- package/dist/components/overlays/ConfirmHost.vue.d.ts +2 -2
- package/dist/components/overlays/ContextMenu.vue.d.ts +2 -2
- package/dist/components/overlays/DropdownMenu.vue.d.ts +2 -2
- package/dist/components/overlays/types.d.ts +2 -2
- package/dist/components/templates/SettingsModal.vue.d.ts +2 -2
- package/dist/composables/useForm.d.ts +8 -1
- package/dist/composables/useForm.mjs +22 -4
- package/dist/composables/useOverlay.d.ts +1 -1
- package/dist/editor/RichTextEditor.vue +95 -9
- package/dist/editor/RichTextEditor.vue.d.ts +4 -1
- package/dist/editor/rich-text-editor.css +21 -0
- package/dist/editor/types.d.ts +1 -0
- package/dist/grid/DataGrid.vue +48 -18
- package/dist/grid/DataGrid.vue.d.ts +6 -1
- package/dist/grid/cells/ImageCell.vue +6 -1
- package/dist/grid/data-grid.css +16 -2
- package/dist/grid/index.d.ts +2 -1
- package/dist/grid/index.mjs +6 -1
- package/dist/grid/modules.d.ts +1 -0
- package/dist/grid/modules.mjs +23 -0
- package/dist/grid/theme.mjs +1 -1
- package/dist/grid/types.d.ts +3 -0
- package/dist/internal/forms/counter.d.ts +18 -0
- package/dist/internal/forms/counter.mjs +31 -0
- package/dist/internal/overlays/OverlayView.vue.d.ts +2 -2
- package/dist/locale/de.mjs +11 -1
- package/dist/locale/en.mjs +11 -1
- package/dist/locale/it.mjs +11 -1
- package/dist/locale/types.d.ts +10 -0
- package/dist/styles/core/form-field.css +6 -0
- package/dist/styles/core/input.css +29 -0
- package/dist/styles/core/textarea.css +10 -0
- package/dist/styles/forms/choice.css +6 -0
- package/package.json +1 -1
|
@@ -53,16 +53,42 @@
|
|
|
53
53
|
</template>
|
|
54
54
|
</div>
|
|
55
55
|
|
|
56
|
-
<form
|
|
56
|
+
<form
|
|
57
|
+
v-if="linkOpen"
|
|
58
|
+
class="k-editor-link"
|
|
59
|
+
@submit.prevent="applyLink"
|
|
60
|
+
@keydown.esc.stop.prevent="closeLink(true)"
|
|
61
|
+
>
|
|
62
|
+
<span v-if="linkTypes.length > 1" class="k-editor-link-type">
|
|
63
|
+
<select
|
|
64
|
+
v-model="linkType"
|
|
65
|
+
class="k-field k-field-sm"
|
|
66
|
+
:aria-label="text.linkType"
|
|
67
|
+
@change="focusLinkInput"
|
|
68
|
+
>
|
|
69
|
+
<option v-for="type in linkTypes" :key="type" :value="type">
|
|
70
|
+
{{ linkTypeLabels[type] }}
|
|
71
|
+
</option>
|
|
72
|
+
</select>
|
|
73
|
+
<Icon name="chevron-up-down" class="k-editor-link-type-icon" />
|
|
74
|
+
</span>
|
|
57
75
|
<input
|
|
58
76
|
ref="linkInputRef"
|
|
59
77
|
v-model="linkUrl"
|
|
60
|
-
class="k-field k-field-sm"
|
|
61
|
-
type="
|
|
62
|
-
inputmode="
|
|
63
|
-
|
|
64
|
-
:
|
|
65
|
-
|
|
78
|
+
class="k-field k-field-sm k-editor-link-target"
|
|
79
|
+
:type="linkInput.type"
|
|
80
|
+
:inputmode="linkInput.inputmode"
|
|
81
|
+
:autocomplete="linkInput.autocomplete"
|
|
82
|
+
:placeholder="linkInput.placeholder"
|
|
83
|
+
:aria-label="linkInput.label"
|
|
84
|
+
/>
|
|
85
|
+
<input
|
|
86
|
+
v-if="linkNeedsText"
|
|
87
|
+
v-model="linkText"
|
|
88
|
+
class="k-field k-field-sm k-editor-link-text"
|
|
89
|
+
type="text"
|
|
90
|
+
:placeholder="text.linkText"
|
|
91
|
+
:aria-label="text.linkText"
|
|
66
92
|
/>
|
|
67
93
|
<Button type="submit" size="xs" :label="text.applyLink" />
|
|
68
94
|
<Button
|
|
@@ -97,6 +123,7 @@ import StarterKit from "@tiptap/starter-kit";
|
|
|
97
123
|
import { EditorContent, useEditor } from "@tiptap/vue-3";
|
|
98
124
|
import { computed, nextTick, onBeforeUnmount, ref, useId, useTemplateRef, watch } from "vue";
|
|
99
125
|
import Button from "../components/core/Button.vue";
|
|
126
|
+
import Icon from "../components/core/Icon.vue";
|
|
100
127
|
import { useFieldControl } from "../composables/useField";
|
|
101
128
|
import { useRovingTabStops } from "../internal/core/roving";
|
|
102
129
|
import LiveRegion from "../internal/core/LiveRegion.vue";
|
|
@@ -125,6 +152,7 @@ const props = defineProps({
|
|
|
125
152
|
headingLabel: { type: String, required: false, default: "level" },
|
|
126
153
|
toolbar: { type: Array, required: false },
|
|
127
154
|
extensions: { type: Array, required: false, default: () => [] },
|
|
155
|
+
linkTypes: { type: Array, required: false, default: () => ["url"] },
|
|
128
156
|
messages: { type: Object, required: false }
|
|
129
157
|
});
|
|
130
158
|
const model = defineModel({ type: [String, Object, null], ...{ default: null } });
|
|
@@ -140,6 +168,40 @@ const toolbarRef = useTemplateRef("toolbarRef");
|
|
|
140
168
|
const linkInputRef = useTemplateRef("linkInputRef");
|
|
141
169
|
const linkOpen = ref(false);
|
|
142
170
|
const linkUrl = ref("");
|
|
171
|
+
const linkText = ref("");
|
|
172
|
+
const linkType = ref("url");
|
|
173
|
+
const linkNeedsText = ref(false);
|
|
174
|
+
const linkPrefixes = { url: "", email: "mailto:", phone: "tel:" };
|
|
175
|
+
const linkTypeLabels = computed(() => ({
|
|
176
|
+
url: text.value.linkTypeUrl,
|
|
177
|
+
email: text.value.linkTypeEmail,
|
|
178
|
+
phone: text.value.linkTypePhone
|
|
179
|
+
}));
|
|
180
|
+
const linkInput = computed(() => {
|
|
181
|
+
if (linkType.value === "email")
|
|
182
|
+
return {
|
|
183
|
+
type: "email",
|
|
184
|
+
inputmode: "email",
|
|
185
|
+
autocomplete: "email",
|
|
186
|
+
placeholder: "name@example.com",
|
|
187
|
+
label: text.value.linkEmail
|
|
188
|
+
};
|
|
189
|
+
if (linkType.value === "phone")
|
|
190
|
+
return {
|
|
191
|
+
type: "tel",
|
|
192
|
+
inputmode: "tel",
|
|
193
|
+
autocomplete: "tel",
|
|
194
|
+
placeholder: "+",
|
|
195
|
+
label: text.value.linkPhone
|
|
196
|
+
};
|
|
197
|
+
return {
|
|
198
|
+
type: "url",
|
|
199
|
+
inputmode: "url",
|
|
200
|
+
autocomplete: "url",
|
|
201
|
+
placeholder: "https://",
|
|
202
|
+
label: text.value.linkUrl
|
|
203
|
+
};
|
|
204
|
+
});
|
|
143
205
|
const editable = computed(() => !props.readonly && !control.disabled.value);
|
|
144
206
|
const showToolbar = computed(() => editable.value);
|
|
145
207
|
function serialize(current) {
|
|
@@ -391,10 +453,26 @@ function toggleLink() {
|
|
|
391
453
|
closeLink();
|
|
392
454
|
return;
|
|
393
455
|
}
|
|
394
|
-
|
|
456
|
+
const current = editor.value;
|
|
457
|
+
const href = current?.getAttributes("link").href ?? "";
|
|
458
|
+
const detected = detectLinkType(href);
|
|
459
|
+
linkType.value = props.linkTypes.includes(detected) ? detected : props.linkTypes[0] ?? "url";
|
|
460
|
+
linkUrl.value = href.slice(linkPrefixes[detected].length);
|
|
461
|
+
linkText.value = "";
|
|
462
|
+
linkNeedsText.value = Boolean(
|
|
463
|
+
current && current.state.selection.empty && !current.isActive("link")
|
|
464
|
+
);
|
|
395
465
|
linkOpen.value = true;
|
|
466
|
+
focusLinkInput();
|
|
467
|
+
}
|
|
468
|
+
function focusLinkInput() {
|
|
396
469
|
nextTick(() => linkInputRef.value?.focus());
|
|
397
470
|
}
|
|
471
|
+
function detectLinkType(href) {
|
|
472
|
+
if (/^mailto:/i.test(href)) return "email";
|
|
473
|
+
if (/^tel:/i.test(href)) return "phone";
|
|
474
|
+
return "url";
|
|
475
|
+
}
|
|
398
476
|
function closeLink(toButton = false) {
|
|
399
477
|
linkOpen.value = false;
|
|
400
478
|
if (!toButton) {
|
|
@@ -406,6 +484,8 @@ function closeLink(toButton = false) {
|
|
|
406
484
|
function normalizeUrl(value) {
|
|
407
485
|
const trimmed = value.trim();
|
|
408
486
|
if (/^(https?:|mailto:|tel:|\/|#)/i.test(trimmed)) return trimmed;
|
|
487
|
+
if (linkType.value === "email") return `mailto:${trimmed}`;
|
|
488
|
+
if (linkType.value === "phone") return `tel:${trimmed.replace(/[^\d+]/g, "")}`;
|
|
409
489
|
return `https://${trimmed}`;
|
|
410
490
|
}
|
|
411
491
|
function applyLink() {
|
|
@@ -415,7 +495,13 @@ function applyLink() {
|
|
|
415
495
|
removeLink();
|
|
416
496
|
return;
|
|
417
497
|
}
|
|
418
|
-
|
|
498
|
+
const href = normalizeUrl(linkUrl.value);
|
|
499
|
+
if (linkNeedsText.value) {
|
|
500
|
+
const label = linkText.value.trim() || linkUrl.value.trim();
|
|
501
|
+
current.chain().focus().insertContent({ type: "text", text: label, marks: [{ type: "link", attrs: { href } }] }).unsetMark("link").run();
|
|
502
|
+
} else {
|
|
503
|
+
current.chain().focus().extendMarkRange("link").setLink({ href }).run();
|
|
504
|
+
}
|
|
419
505
|
linkOpen.value = false;
|
|
420
506
|
}
|
|
421
507
|
function removeLink() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Editor } from '@tiptap/vue-3';
|
|
2
2
|
import type { Extensions } from '@tiptap/vue-3';
|
|
3
|
-
import type { EditorFormat, EditorHeadingLabel, EditorHeadingLevel, EditorMessages, EditorToolbar, EditorValue } from './types';
|
|
3
|
+
import type { EditorFormat, EditorHeadingLabel, EditorHeadingLevel, EditorLinkType, EditorMessages, EditorToolbar, EditorValue } from './types';
|
|
4
4
|
declare const __VLS_export: import("vue").DefineComponent<{
|
|
5
5
|
format?: EditorFormat;
|
|
6
6
|
placeholder?: string | undefined;
|
|
@@ -17,6 +17,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
17
17
|
headingLabel?: EditorHeadingLabel;
|
|
18
18
|
toolbar?: EditorToolbar;
|
|
19
19
|
extensions?: Extensions;
|
|
20
|
+
linkTypes?: EditorLinkType[];
|
|
20
21
|
messages?: Partial<EditorMessages>;
|
|
21
22
|
modelValue?: EditorValue;
|
|
22
23
|
key?: PropertyKey | undefined;
|
|
@@ -231,6 +232,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
231
232
|
headingLabel?: EditorHeadingLabel;
|
|
232
233
|
toolbar?: EditorToolbar;
|
|
233
234
|
extensions?: Extensions;
|
|
235
|
+
linkTypes?: EditorLinkType[];
|
|
234
236
|
messages?: Partial<EditorMessages>;
|
|
235
237
|
modelValue?: EditorValue;
|
|
236
238
|
key?: PropertyKey | undefined;
|
|
@@ -433,6 +435,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
433
435
|
headings: EditorHeadingLevel[];
|
|
434
436
|
headingLabel: EditorHeadingLabel;
|
|
435
437
|
extensions: Extensions;
|
|
438
|
+
linkTypes: EditorLinkType[];
|
|
436
439
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
437
440
|
declare const _default: typeof __VLS_export;
|
|
438
441
|
export default _default;
|
|
@@ -131,6 +131,27 @@
|
|
|
131
131
|
width: auto;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
.k-editor-link-type {
|
|
135
|
+
position: relative;
|
|
136
|
+
display: inline-flex;
|
|
137
|
+
flex: 0 0 auto;
|
|
138
|
+
align-items: center;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.k-editor-link .k-editor-link-type > .k-field {
|
|
142
|
+
flex: 0 0 auto;
|
|
143
|
+
padding-right: 1.75rem;
|
|
144
|
+
cursor: pointer;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.k-editor-link-type-icon {
|
|
148
|
+
--k-icon-size: 0.875rem;
|
|
149
|
+
position: absolute;
|
|
150
|
+
right: 0.5rem;
|
|
151
|
+
color: var(--k-text-dimmed);
|
|
152
|
+
pointer-events: none;
|
|
153
|
+
}
|
|
154
|
+
|
|
134
155
|
.k-editor-content {
|
|
135
156
|
flex: 1;
|
|
136
157
|
min-width: 0;
|
package/dist/editor/types.d.ts
CHANGED
|
@@ -5,5 +5,6 @@ export type EditorValue = string | JSONContent | null;
|
|
|
5
5
|
export type EditorMessages = KMessages['editor'];
|
|
6
6
|
export type EditorHeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
7
7
|
export type EditorHeadingLabel = 'level' | 'relative';
|
|
8
|
+
export type EditorLinkType = 'url' | 'email' | 'phone';
|
|
8
9
|
export type EditorToolbarItem = 'undo' | 'redo' | 'headings' | `h${EditorHeadingLevel}` | 'bold' | 'italic' | 'underline' | 'strike' | 'code' | 'bulletList' | 'orderedList' | 'blockquote' | 'link' | '|';
|
|
9
10
|
export type EditorToolbar = EditorToolbarItem[] | EditorToolbarItem[][];
|
package/dist/grid/DataGrid.vue
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
class="k-data-grid"
|
|
4
|
-
:class="[
|
|
4
|
+
:class="[
|
|
5
|
+
`k-data-grid-${density}`,
|
|
6
|
+
{ 'is-loading': loading, 'is-auto-height': autoHeight, 'is-fill': fill && !autoHeight }
|
|
7
|
+
]"
|
|
5
8
|
>
|
|
6
9
|
<GridToolbar
|
|
7
10
|
v-if="toolbar"
|
|
@@ -23,7 +26,7 @@
|
|
|
23
26
|
role="region"
|
|
24
27
|
:aria-label="label ?? text.label"
|
|
25
28
|
:aria-busy="loading ? 'true' : void 0"
|
|
26
|
-
:style="autoHeight ? void 0 : { height }"
|
|
29
|
+
:style="autoHeight || fill ? void 0 : { height }"
|
|
27
30
|
>
|
|
28
31
|
<AgGridVue
|
|
29
32
|
v-if="mounted"
|
|
@@ -33,23 +36,23 @@
|
|
|
33
36
|
:row-data="rows"
|
|
34
37
|
:column-defs="columnDefs"
|
|
35
38
|
:default-col-def="defaultColDef"
|
|
36
|
-
:get-row-id="
|
|
39
|
+
:get-row-id="rowIdGetter"
|
|
37
40
|
:loading="loading"
|
|
38
41
|
:locale-text="gridLocaleText"
|
|
39
|
-
:context="
|
|
40
|
-
:overlay-no-rows-template="noRowsTemplate"
|
|
41
|
-
:overlay-loading-template="loadingTemplate"
|
|
42
|
+
:context="gridContext"
|
|
43
|
+
:overlay-no-rows-template="gridOptions?.overlayNoRowsTemplate ?? noRowsTemplate"
|
|
44
|
+
:overlay-loading-template="gridOptions?.overlayLoadingTemplate ?? loadingTemplate"
|
|
42
45
|
:quick-filter-text="serverPagination ? void 0 : query"
|
|
43
|
-
:row-selection="
|
|
46
|
+
:row-selection="gridRowSelection"
|
|
44
47
|
:pagination="paginated"
|
|
45
48
|
:pagination-page-size="pageSize"
|
|
46
49
|
:pagination-page-size-selector="false"
|
|
47
50
|
:suppress-pagination-panel="true"
|
|
48
|
-
:auto-size-strategy="
|
|
51
|
+
:auto-size-strategy="gridAutoSizeStrategy"
|
|
49
52
|
:dom-layout="autoHeight ? 'autoHeight' : 'normal'"
|
|
50
53
|
:row-height="rowHeight ?? gridOptions?.rowHeight"
|
|
51
54
|
:header-height="headerHeight ?? gridOptions?.headerHeight"
|
|
52
|
-
:tooltip-show-delay="600"
|
|
55
|
+
:tooltip-show-delay="gridOptions?.tooltipShowDelay ?? 600"
|
|
53
56
|
:suppress-cell-focus="false"
|
|
54
57
|
v-on="gridEvents"
|
|
55
58
|
/>
|
|
@@ -71,6 +74,9 @@
|
|
|
71
74
|
class="k-data-grid-pager"
|
|
72
75
|
size="sm"
|
|
73
76
|
compact
|
|
77
|
+
:show-edges="showEdges"
|
|
78
|
+
:show-jump="showJump"
|
|
79
|
+
:loading="loading"
|
|
74
80
|
:total="totalRows"
|
|
75
81
|
:page="page"
|
|
76
82
|
:page-size="pageSize"
|
|
@@ -104,18 +110,24 @@ import { useLiveMessage } from "../internal/core/live";
|
|
|
104
110
|
import { readStorageJson, removeStorage, writeStorageJson } from "../internal/core/storage";
|
|
105
111
|
import GridToolbar from "./GridToolbar.vue";
|
|
106
112
|
import { escapeHtml } from "../internal/core/text";
|
|
107
|
-
import {
|
|
113
|
+
import {
|
|
114
|
+
registerGridEditorModules,
|
|
115
|
+
registerGridFilterModules,
|
|
116
|
+
registerGridModules
|
|
117
|
+
} from "./modules";
|
|
108
118
|
import { getGridTheme } from "./theme";
|
|
109
119
|
registerGridModules();
|
|
110
120
|
const props = defineProps({
|
|
111
121
|
rows: { type: Array, required: false, default: () => [] },
|
|
112
122
|
columns: { type: Array, required: true },
|
|
113
123
|
rowIdKey: { type: String, required: false },
|
|
124
|
+
getRowId: { type: Function, required: false },
|
|
114
125
|
storageKey: { type: String, required: false },
|
|
115
126
|
density: { type: String, required: false, default: "normal" },
|
|
116
127
|
selectable: { type: [Boolean, String], required: false, default: false },
|
|
117
128
|
loading: { type: Boolean, required: false },
|
|
118
129
|
height: { type: String, required: false, default: "28rem" },
|
|
130
|
+
fill: { type: Boolean, required: false },
|
|
119
131
|
autoHeight: { type: Boolean, required: false },
|
|
120
132
|
label: { type: String, required: false },
|
|
121
133
|
toolbar: { type: Boolean, required: false, default: false },
|
|
@@ -126,6 +138,8 @@ const props = defineProps({
|
|
|
126
138
|
searchDebounce: { type: Number, required: false, default: 0 },
|
|
127
139
|
serverSort: { type: Boolean, required: false },
|
|
128
140
|
pagination: { type: Boolean, required: false },
|
|
141
|
+
showEdges: { type: Boolean, required: false },
|
|
142
|
+
showJump: { type: Boolean, required: false },
|
|
129
143
|
serverPagination: { type: Boolean, required: false },
|
|
130
144
|
total: { type: Number, required: false, default: 0 },
|
|
131
145
|
pageSizes: { type: Array, required: false, default: () => [10, 25, 50, 100] },
|
|
@@ -135,7 +149,8 @@ const props = defineProps({
|
|
|
135
149
|
rowHeight: { type: Number, required: false },
|
|
136
150
|
headerHeight: { type: Number, required: false },
|
|
137
151
|
headerText: { type: Function, required: false },
|
|
138
|
-
filterable: { type: Boolean, required: false }
|
|
152
|
+
filterable: { type: Boolean, required: false },
|
|
153
|
+
editable: { type: Boolean, required: false }
|
|
139
154
|
});
|
|
140
155
|
const emit = defineEmits(["rowClick", "selectionChange", "sortChange", "filterChange", "copy"]);
|
|
141
156
|
const query = defineModel("query", { type: String, ...{ default: "" } });
|
|
@@ -143,6 +158,10 @@ const page = defineModel("page", { type: Number, ...{ default: 1 } });
|
|
|
143
158
|
const pageSize = defineModel("pageSize", { type: Number, ...{ default: 25 } });
|
|
144
159
|
const sort = defineModel("sort", { type: null, ...{ default: void 0 } });
|
|
145
160
|
if (props.filterable) registerGridFilterModules();
|
|
161
|
+
function hasEditableColumn() {
|
|
162
|
+
return props.editable || Boolean(props.gridOptions?.defaultColDef?.editable) || props.columns.some((column) => Boolean(column.editable));
|
|
163
|
+
}
|
|
164
|
+
if (hasEditableColumn()) registerGridEditorModules();
|
|
146
165
|
const columnDefs = computed(() => {
|
|
147
166
|
const headerText = props.headerText;
|
|
148
167
|
if (!headerText) return props.columns;
|
|
@@ -180,8 +199,10 @@ const gridLocaleText = computed(() => ({
|
|
|
180
199
|
previousPage: text.value.previousPage,
|
|
181
200
|
noRowsToShow: text.value.noRows,
|
|
182
201
|
loadingOoo: text.value.loading,
|
|
202
|
+
...props.gridOptions?.localeText,
|
|
183
203
|
...props.localeText
|
|
184
204
|
}));
|
|
205
|
+
const gridContext = computed(() => ({ ...props.gridOptions?.context, ...cellContext.value }));
|
|
185
206
|
const live = useLiveMessage();
|
|
186
207
|
let announcedCount = null;
|
|
187
208
|
const theme = computed(() => getGridTheme(props.density));
|
|
@@ -204,8 +225,8 @@ const noRowsTemplate = computed(
|
|
|
204
225
|
const loadingTemplate = computed(
|
|
205
226
|
() => `<div class="k-data-grid-overlay"><span class="k-spinner k-spinner-md" aria-hidden="true"></span></div>`
|
|
206
227
|
);
|
|
207
|
-
const
|
|
208
|
-
if (!props.selectable) return
|
|
228
|
+
const gridRowSelection = computed(() => {
|
|
229
|
+
if (!props.selectable) return props.gridOptions?.rowSelection;
|
|
209
230
|
return {
|
|
210
231
|
mode: props.selectable === "single" ? "singleRow" : "multiRow",
|
|
211
232
|
enableClickSelection: false
|
|
@@ -218,7 +239,8 @@ const defaultColDef = computed(() => ({
|
|
|
218
239
|
minWidth: 80,
|
|
219
240
|
comparator: props.serverSort ? () => 0 : void 0,
|
|
220
241
|
valueFormatter: (params) => isEmpty(params.value) ? "-" : String(params.value),
|
|
221
|
-
cellRenderer: renderCell
|
|
242
|
+
cellRenderer: renderCell,
|
|
243
|
+
...props.gridOptions?.defaultColDef
|
|
222
244
|
}));
|
|
223
245
|
function isEmpty(value) {
|
|
224
246
|
return value === null || value === void 0 || value === "";
|
|
@@ -241,12 +263,20 @@ function renderCell(params) {
|
|
|
241
263
|
}
|
|
242
264
|
const storageName = computed(() => props.storageKey ? `k-grid:${props.storageKey}` : null);
|
|
243
265
|
const hasStoredState = ref(false);
|
|
244
|
-
const
|
|
245
|
-
(
|
|
246
|
-
)
|
|
247
|
-
|
|
266
|
+
const gridAutoSizeStrategy = computed(() => {
|
|
267
|
+
if (hasStoredState.value) return void 0;
|
|
268
|
+
if (props.gridOptions && "autoSizeStrategy" in props.gridOptions)
|
|
269
|
+
return props.gridOptions.autoSizeStrategy;
|
|
270
|
+
return { type: "fitGridWidth", defaultMinWidth: 100 };
|
|
271
|
+
});
|
|
272
|
+
function getRowIdByKey(params) {
|
|
248
273
|
return String(params.data[props.rowIdKey]);
|
|
249
274
|
}
|
|
275
|
+
const rowIdGetter = computed(() => {
|
|
276
|
+
if (props.getRowId) return props.getRowId;
|
|
277
|
+
if (props.rowIdKey) return getRowIdByKey;
|
|
278
|
+
return props.gridOptions?.getRowId;
|
|
279
|
+
});
|
|
250
280
|
function readStoredState() {
|
|
251
281
|
if (!storageName.value) return null;
|
|
252
282
|
const stored = readStorageJson(storageName.value);
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import type { FilterChangedEvent, FilterModel, ColDef, GridApi, GridOptions, RowClickedEvent } from 'ag-grid-community';
|
|
1
|
+
import type { FilterChangedEvent, FilterModel, ColDef, GetRowIdParams, GridApi, GridOptions, RowClickedEvent } from 'ag-grid-community';
|
|
2
2
|
import type { GridDensity, GridMessages, GridSelection, GridSortChange } from './types';
|
|
3
3
|
declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
4
4
|
props: import("vue").PublicProps & __VLS_PrettifyLocal<({
|
|
5
5
|
rows?: T[];
|
|
6
6
|
columns: ColDef<T>[];
|
|
7
7
|
rowIdKey?: keyof T & string;
|
|
8
|
+
getRowId?: (params: GetRowIdParams<T>) => string;
|
|
8
9
|
storageKey?: string;
|
|
9
10
|
density?: GridDensity;
|
|
10
11
|
selectable?: GridSelection;
|
|
11
12
|
loading?: boolean;
|
|
12
13
|
height?: string;
|
|
14
|
+
fill?: boolean;
|
|
13
15
|
autoHeight?: boolean;
|
|
14
16
|
label?: string;
|
|
15
17
|
toolbar?: boolean;
|
|
@@ -20,6 +22,8 @@ declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_se
|
|
|
20
22
|
searchDebounce?: number;
|
|
21
23
|
serverSort?: boolean;
|
|
22
24
|
pagination?: boolean;
|
|
25
|
+
showEdges?: boolean;
|
|
26
|
+
showJump?: boolean;
|
|
23
27
|
serverPagination?: boolean;
|
|
24
28
|
total?: number;
|
|
25
29
|
pageSizes?: number[];
|
|
@@ -30,6 +34,7 @@ declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_se
|
|
|
30
34
|
headerHeight?: number;
|
|
31
35
|
headerText?: (field: string, column: ColDef<T>) => string | undefined;
|
|
32
36
|
filterable?: boolean;
|
|
37
|
+
editable?: boolean;
|
|
33
38
|
} & {
|
|
34
39
|
query?: string;
|
|
35
40
|
page?: number;
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
<img
|
|
3
3
|
v-if="src"
|
|
4
4
|
class="k-data-grid-image"
|
|
5
|
-
:class="{ 'is-rounded': params.rounded }"
|
|
5
|
+
:class="{ 'is-rounded': params.rounded, 'is-contain': params.fit === 'contain' }"
|
|
6
|
+
:style="sizeStyle"
|
|
6
7
|
:src="src"
|
|
7
8
|
:alt="alt"
|
|
8
9
|
loading="lazy"
|
|
@@ -12,6 +13,7 @@
|
|
|
12
13
|
v-else
|
|
13
14
|
class="k-data-grid-image is-empty"
|
|
14
15
|
:class="{ 'is-rounded': params.rounded }"
|
|
16
|
+
:style="sizeStyle"
|
|
15
17
|
aria-hidden="true"
|
|
16
18
|
>
|
|
17
19
|
<Icon name="photo" />
|
|
@@ -28,5 +30,8 @@ const src = computed(() => {
|
|
|
28
30
|
const raw = props.params.value;
|
|
29
31
|
return typeof raw === "string" && raw ? raw : "";
|
|
30
32
|
});
|
|
33
|
+
const sizeStyle = computed(
|
|
34
|
+
() => props.params.size ? { "--k-grid-image-size": props.params.size } : void 0
|
|
35
|
+
);
|
|
31
36
|
const alt = computed(() => props.params.alt?.(props.params.data) ?? "");
|
|
32
37
|
</script>
|
package/dist/grid/data-grid.css
CHANGED
|
@@ -33,6 +33,16 @@
|
|
|
33
33
|
min-height: 8rem;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
.k-data-grid.is-fill {
|
|
37
|
+
flex: 1 1 0%;
|
|
38
|
+
height: 100%;
|
|
39
|
+
min-height: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.k-data-grid.is-fill > .k-data-grid-body {
|
|
43
|
+
flex: 1 1 0%;
|
|
44
|
+
}
|
|
45
|
+
|
|
36
46
|
.k-data-grid-ag {
|
|
37
47
|
height: 100%;
|
|
38
48
|
}
|
|
@@ -174,8 +184,8 @@
|
|
|
174
184
|
|
|
175
185
|
.k-data-grid-image {
|
|
176
186
|
display: block;
|
|
177
|
-
width: 1.75rem;
|
|
178
|
-
height: 1.75rem;
|
|
187
|
+
width: var(--k-grid-image-size, 1.75rem);
|
|
188
|
+
height: var(--k-grid-image-size, 1.75rem);
|
|
179
189
|
object-fit: cover;
|
|
180
190
|
background: var(--k-fill);
|
|
181
191
|
border-radius: var(--k-radius-sm);
|
|
@@ -188,6 +198,10 @@
|
|
|
188
198
|
--k-icon-size: 1rem;
|
|
189
199
|
}
|
|
190
200
|
|
|
201
|
+
.k-data-grid-image.is-contain {
|
|
202
|
+
object-fit: contain;
|
|
203
|
+
}
|
|
204
|
+
|
|
191
205
|
.k-data-grid-image.is-rounded {
|
|
192
206
|
border-radius: var(--k-radius-full);
|
|
193
207
|
}
|
package/dist/grid/index.d.ts
CHANGED
|
@@ -2,9 +2,10 @@ export { default as DataGrid } from './DataGrid.vue';
|
|
|
2
2
|
export { default as GridToolbar } from './GridToolbar.vue';
|
|
3
3
|
export { default as BooleanCell } from './cells/BooleanCell.vue';
|
|
4
4
|
export { default as DateCell } from './cells/DateCell.vue';
|
|
5
|
+
export { default as EmptyCell } from './cells/EmptyCell.vue';
|
|
5
6
|
export { default as BadgeCell } from './cells/BadgeCell.vue';
|
|
6
7
|
export { default as ImageCell } from './cells/ImageCell.vue';
|
|
7
8
|
export { default as LinkCell } from './cells/LinkCell.vue';
|
|
8
|
-
export { registerGridFilterModules, registerGridModules } from './modules';
|
|
9
|
+
export { registerGridEditorModules, registerGridFilterModules, registerGridModules, } from './modules';
|
|
9
10
|
export { createGridTheme } from './theme';
|
|
10
11
|
export type * from './types';
|
package/dist/grid/index.mjs
CHANGED
|
@@ -2,8 +2,13 @@ export { default as DataGrid } from "./DataGrid.vue";
|
|
|
2
2
|
export { default as GridToolbar } from "./GridToolbar.vue";
|
|
3
3
|
export { default as BooleanCell } from "./cells/BooleanCell.vue";
|
|
4
4
|
export { default as DateCell } from "./cells/DateCell.vue";
|
|
5
|
+
export { default as EmptyCell } from "./cells/EmptyCell.vue";
|
|
5
6
|
export { default as BadgeCell } from "./cells/BadgeCell.vue";
|
|
6
7
|
export { default as ImageCell } from "./cells/ImageCell.vue";
|
|
7
8
|
export { default as LinkCell } from "./cells/LinkCell.vue";
|
|
8
|
-
export {
|
|
9
|
+
export {
|
|
10
|
+
registerGridEditorModules,
|
|
11
|
+
registerGridFilterModules,
|
|
12
|
+
registerGridModules
|
|
13
|
+
} from "./modules.mjs";
|
|
9
14
|
export { createGridTheme } from "./theme.mjs";
|
package/dist/grid/modules.d.ts
CHANGED
package/dist/grid/modules.mjs
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CellApiModule,
|
|
3
|
+
CheckboxEditorModule,
|
|
4
|
+
CustomEditorModule,
|
|
5
|
+
DateEditorModule,
|
|
6
|
+
LargeTextEditorModule,
|
|
7
|
+
NumberEditorModule,
|
|
8
|
+
SelectEditorModule,
|
|
9
|
+
TextEditorModule,
|
|
10
|
+
UndoRedoEditModule,
|
|
3
11
|
CellStyleModule,
|
|
4
12
|
ClientSideRowModelApiModule,
|
|
5
13
|
ClientSideRowModelModule,
|
|
@@ -51,3 +59,18 @@ export function registerGridFilterModules() {
|
|
|
51
59
|
filtersRegistered = true;
|
|
52
60
|
ModuleRegistry.registerModules([TextFilterModule, NumberFilterModule, DateFilterModule]);
|
|
53
61
|
}
|
|
62
|
+
let editorsRegistered = false;
|
|
63
|
+
export function registerGridEditorModules() {
|
|
64
|
+
if (editorsRegistered) return;
|
|
65
|
+
editorsRegistered = true;
|
|
66
|
+
ModuleRegistry.registerModules([
|
|
67
|
+
TextEditorModule,
|
|
68
|
+
LargeTextEditorModule,
|
|
69
|
+
NumberEditorModule,
|
|
70
|
+
DateEditorModule,
|
|
71
|
+
CheckboxEditorModule,
|
|
72
|
+
SelectEditorModule,
|
|
73
|
+
CustomEditorModule,
|
|
74
|
+
UndoRedoEditModule
|
|
75
|
+
]);
|
|
76
|
+
}
|
package/dist/grid/theme.mjs
CHANGED
|
@@ -17,7 +17,7 @@ export function createGridTheme(density) {
|
|
|
17
17
|
headerBackgroundColor: "var(--k-grid-header-background, var(--k-subtle))",
|
|
18
18
|
headerTextColor: "var(--k-grid-header-text, var(--k-text-muted))",
|
|
19
19
|
headerFontFamily: "var(--k-grid-header-font, var(--k-font-sans))",
|
|
20
|
-
headerFontSize:
|
|
20
|
+
headerFontSize: "var(--k-grid-header-font-size, 12px)",
|
|
21
21
|
headerFontWeight: "var(--k-grid-header-font-weight, var(--k-font-weight-medium, 500))",
|
|
22
22
|
headerRowBorder: { color: "var(--k-line)" },
|
|
23
23
|
headerColumnBorder: false,
|
package/dist/grid/types.d.ts
CHANGED
|
@@ -45,9 +45,12 @@ export interface BadgeCellParams {
|
|
|
45
45
|
labels?: Record<string, string>;
|
|
46
46
|
defaultTone?: Tone;
|
|
47
47
|
}
|
|
48
|
+
export type ImageCellFit = 'cover' | 'contain';
|
|
48
49
|
export interface ImageCellParams<T = unknown> {
|
|
49
50
|
alt?: (data: T | undefined) => string;
|
|
50
51
|
rounded?: boolean;
|
|
52
|
+
fit?: ImageCellFit;
|
|
53
|
+
size?: string;
|
|
51
54
|
}
|
|
52
55
|
export interface LinkCellParams<T = unknown> {
|
|
53
56
|
href?: (value: unknown, data: T | undefined) => string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface CharacterCounterOptions {
|
|
2
|
+
enabled: () => boolean | undefined;
|
|
3
|
+
value: () => unknown;
|
|
4
|
+
attrs: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
export interface CharacterCounterState {
|
|
7
|
+
id: string;
|
|
8
|
+
visible: boolean;
|
|
9
|
+
length: number;
|
|
10
|
+
max: number;
|
|
11
|
+
atLimit: boolean;
|
|
12
|
+
text: string;
|
|
13
|
+
label: string;
|
|
14
|
+
limitMessage: string;
|
|
15
|
+
width: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function useCharacterCounter(options: CharacterCounterOptions): () => CharacterCounterState;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useId } from "vue";
|
|
2
|
+
import { useLocale } from "../../composables/useLocale.mjs";
|
|
3
|
+
function readLimit(attrs) {
|
|
4
|
+
const raw = attrs.maxlength ?? attrs.maxLength;
|
|
5
|
+
if (raw === void 0 || raw === null || raw === "" || raw === false) return void 0;
|
|
6
|
+
const limit = Number(raw);
|
|
7
|
+
return Number.isFinite(limit) && limit >= 0 ? Math.trunc(limit) : void 0;
|
|
8
|
+
}
|
|
9
|
+
export function useCharacterCounter(options) {
|
|
10
|
+
const { t } = useLocale();
|
|
11
|
+
const id = useId();
|
|
12
|
+
return () => {
|
|
13
|
+
const max = readLimit(options.attrs);
|
|
14
|
+
const visible = Boolean(options.enabled()) && max !== void 0;
|
|
15
|
+
const value = options.value();
|
|
16
|
+
const length = value === null || value === void 0 ? 0 : String(value).length;
|
|
17
|
+
const limit = max ?? 0;
|
|
18
|
+
const atLimit = visible && length >= limit;
|
|
19
|
+
return {
|
|
20
|
+
id,
|
|
21
|
+
visible,
|
|
22
|
+
length,
|
|
23
|
+
max: limit,
|
|
24
|
+
atLimit,
|
|
25
|
+
text: `${length} / ${limit}`,
|
|
26
|
+
label: visible ? t("form.characterCount", { count: length, max: limit }) : "",
|
|
27
|
+
limitMessage: atLimit ? t("form.characterLimitReached") : "",
|
|
28
|
+
width: String(limit).length * 2 + 3
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -208,9 +208,9 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
208
208
|
onVnodeBeforeUnmount?: (((vnode: import("vue").VNode) => void) | ((vnode: import("vue").VNode) => void)[]) | undefined;
|
|
209
209
|
onVnodeUnmounted?: (((vnode: import("vue").VNode) => void) | ((vnode: import("vue").VNode) => void)[]) | undefined;
|
|
210
210
|
flush?: boolean;
|
|
211
|
+
sheet?: boolean;
|
|
211
212
|
onCancel?: ((payload: Event) => void) | undefined;
|
|
212
213
|
side?: import("../../index.ts").DrawerSide;
|
|
213
|
-
sheet?: boolean;
|
|
214
214
|
onOpen?: ((() => any) & (() => any)) | undefined;
|
|
215
215
|
closeLabel?: string;
|
|
216
216
|
rootClass?: unknown;
|
|
@@ -431,9 +431,9 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
431
431
|
onVnodeBeforeUnmount?: (((vnode: import("vue").VNode) => void) | ((vnode: import("vue").VNode) => void)[]) | undefined;
|
|
432
432
|
onVnodeUnmounted?: (((vnode: import("vue").VNode) => void) | ((vnode: import("vue").VNode) => void)[]) | undefined;
|
|
433
433
|
flush?: boolean;
|
|
434
|
+
sheet?: boolean;
|
|
434
435
|
onCancel?: ((payload: Event) => void) | undefined;
|
|
435
436
|
side?: import("../../index.ts").DrawerSide;
|
|
436
|
-
sheet?: boolean;
|
|
437
437
|
onOpen?: ((() => any) & (() => any)) | undefined;
|
|
438
438
|
closeLabel?: string;
|
|
439
439
|
rootClass?: unknown;
|