vueye-table 3.0.0-alpha.9 → 3.0.0-beta.2

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/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { inferColumns } from "@vueye-table/core";
2
- import { DataTableBody, DataTableCaption, DataTableCell, DataTableRoot, DataTableRow, DataTableSelectAll, DataTableSelectRow, DataTableViewport, hierarchyProps, resolveTreeColumn, virtualProps } from "@vueye-table/headless";
3
- import { VtColumnVisibility, VtEmpty, VtExpandToggle, VtGrid, VtHeader, VtLoadMore, VtPageSize, VtPagination, VtSearch, VtStatus, VtToolbar, VtTreeCell } from "@vueye-table/styled";
4
- import { provideDataTable, useDataTable } from "@vueye-table/vue";
5
- import { computed, defineComponent, h } from "vue";
2
+ import { DataTableBody, DataTableCaption, DataTableCell, DataTableEditCell, DataTableEditRoot, DataTableRoot, DataTableRow, DataTableSelectAll, DataTableSelectRow, DataTableViewport, hierarchyProps, resolveTreeColumn, virtualProps } from "@vueye-table/headless";
3
+ import { VtColumnVisibility, VtEmpty, VtExpandToggle, VtGrid, VtHeader, VtLoadMore, VtPageSize, VtPagination, VtRowActions, VtSearch, VtStatus, VtToolbar, VtTreeCell } from "@vueye-table/styled";
4
+ import { provideDataTable, provideTableLocale, tableLocaleKey, useDataTable, useTableLocale } from "@vueye-table/vue";
5
+ import { computed, defineComponent, h, mergeProps } from "vue";
6
6
 
7
7
  export * from "@vueye-table/core"
8
8
 
@@ -55,6 +55,30 @@ const CellContent = defineComponent({
55
55
  });
56
56
  /** Props both full components share. */
57
57
  const commonProps = {
58
+ validateRow: {
59
+ type: Function,
60
+ default: void 0
61
+ },
62
+ asyncValidation: {
63
+ type: String,
64
+ default: void 0
65
+ },
66
+ createRow: {
67
+ type: Function,
68
+ default: void 0
69
+ },
70
+ setParentKey: {
71
+ type: Function,
72
+ default: void 0
73
+ },
74
+ addRow: {
75
+ type: Boolean,
76
+ default: false
77
+ },
78
+ removeRows: {
79
+ type: Boolean,
80
+ default: false
81
+ },
58
82
  ...virtualProps,
59
83
  ...hierarchyProps,
60
84
  rowCanExpand: {
@@ -160,10 +184,37 @@ const commonProps = {
160
184
  type: Boolean,
161
185
  default: false
162
186
  },
187
+ /**
188
+ * `"light"` or `"dark"` forces a palette; by default the table follows `prefers-color-scheme`.
189
+ * `"inherit"` uses no built-in palette: the host declares the `--vt-*` tokens on an ancestor,
190
+ * in its own light and dark themes.
191
+ */
163
192
  theme: {
164
193
  type: String,
165
194
  default: void 0
166
195
  },
196
+ /**
197
+ * The BCP 47 locale numbers are written and text is ordered in, such as `"fr"` or `"ar-DZ"`.
198
+ * Defaults to the plugin's, then the runtime's. Ordering reads it once, when the table is
199
+ * created; give the table a new `key` to change it.
200
+ */
201
+ locale: {
202
+ type: String,
203
+ default: void 0
204
+ },
205
+ /** The host's words for what the table shows and announces, over the plugin's and English. */
206
+ messages: {
207
+ type: Object,
208
+ default: void 0
209
+ },
210
+ /**
211
+ * How search and text filters read text. Defaults to `foldText`: case, accents and Arabic
212
+ * letter shapes ignored. Read once, when the table is created.
213
+ */
214
+ normalizeText: {
215
+ type: Function,
216
+ default: void 0
217
+ },
167
218
  /** A CSS height that makes the body scroll, such as `"24rem"`. */
168
219
  maxHeight: {
169
220
  type: String,
@@ -173,9 +224,10 @@ const commonProps = {
173
224
  type: Boolean,
174
225
  default: true
175
226
  },
227
+ /** Defaults to the messages' `searchPlaceholder`. */
176
228
  searchPlaceholder: {
177
229
  type: String,
178
- default: "Search…"
230
+ default: void 0
179
231
  },
180
232
  columnToggle: {
181
233
  type: Boolean,
@@ -223,16 +275,34 @@ const commonProps = {
223
275
  default: "all"
224
276
  }
225
277
  };
226
- const stateEmits = [
227
- "update:page",
228
- "update:pageSize",
229
- "update:sorting",
230
- "update:search",
231
- "update:filters",
232
- "update:hiddenColumns",
233
- "update:selected",
234
- "update:expanded"
235
- ];
278
+ const editingEmits = {
279
+ "update:data": (_data) => true,
280
+ edit: (_changes) => true,
281
+ save: (_result) => true,
282
+ cancel: (_key) => true,
283
+ "edit-issues": (_issues) => true,
284
+ "edit-error": (_issues) => true
285
+ };
286
+ function editingOptions(props) {
287
+ return {
288
+ validateRow: props.validateRow,
289
+ asyncValidation: props.asyncValidation,
290
+ createRow: props.createRow,
291
+ setParentKey: props.setParentKey
292
+ };
293
+ }
294
+ /** The `v-model` events of table state, typed by the value each carries. */
295
+ const stateEmitValidators = {
296
+ "update:page": (_page) => true,
297
+ "update:pageSize": (_pageSize) => true,
298
+ "update:sorting": (_sorting) => true,
299
+ "update:search": (_search) => true,
300
+ "update:filters": (_filters) => true,
301
+ "update:hiddenColumns": (_hiddenColumns) => true,
302
+ "update:selected": (_selected) => true,
303
+ "update:expanded": (_expanded) => true
304
+ };
305
+ const stateEmits = Object.keys(stateEmitValidators);
236
306
  /** The state a parent controls through `v-model`, as a table state patch. */
237
307
  function controlledState(props, current) {
238
308
  return {
@@ -271,7 +341,7 @@ function expansionOptions(props, detail) {
271
341
  getParentKey: props.getParentKey,
272
342
  hasChildren: props.hasChildren,
273
343
  loadChildren: props.loadChildren,
274
- treeFilter: props.treeFilter,
344
+ treeFilter: () => props.treeFilter,
275
345
  paginateBy: props.paginateBy
276
346
  };
277
347
  }
@@ -353,9 +423,10 @@ const VueyeGrid = defineComponent({
353
423
  type: Boolean,
354
424
  default: false
355
425
  },
426
+ /** The grid's accessible name. Defaults to the messages' `spreadsheet`. */
356
427
  label: {
357
428
  type: String,
358
- default: "Spreadsheet"
429
+ default: void 0
359
430
  },
360
431
  /** Show undo, redo, and CSV export buttons. */
361
432
  toolbar: {
@@ -364,7 +435,8 @@ const VueyeGrid = defineComponent({
364
435
  }
365
436
  },
366
437
  emits: {
367
- ...Object.fromEntries(stateEmits.map((name) => [name, null])),
438
+ ...editingEmits,
439
+ ...stateEmitValidators,
368
440
  "state-change": (_state) => true,
369
441
  "update:data": (_data) => true,
370
442
  edit: (_changes) => true,
@@ -374,11 +446,27 @@ const VueyeGrid = defineComponent({
374
446
  collapse: (_item, _row) => true
375
447
  },
376
448
  setup(props, { emit, slots, expose, attrs }) {
449
+ const inherited = useTableLocale();
450
+ const locale = provideTableLocale(() => ({
451
+ locale: props.locale,
452
+ messages: props.messages
453
+ }));
377
454
  const resolveColumns = createColumnResolver();
378
- const columns = computed(() => resolveColumns(props.columns, props.data).map((column) => ({
379
- ...column,
380
- editable: props.editable ? column.editable ?? true : false
381
- })));
455
+ let previousColumns;
456
+ const columns = computed(() => {
457
+ const source = resolveColumns(props.columns, props.data);
458
+ if (previousColumns?.source === source && previousColumns.editable === props.editable) return previousColumns.columns;
459
+ const resolved = source.map((column) => ({
460
+ ...column,
461
+ editable: props.editable ? column.editable ?? true : false
462
+ }));
463
+ previousColumns = {
464
+ source,
465
+ editable: props.editable,
466
+ columns: resolved
467
+ };
468
+ return resolved;
469
+ });
382
470
  const everyRow = () => Math.max(1, props.data.length);
383
471
  const initialPagination = {
384
472
  page: props.page ?? 1,
@@ -387,6 +475,7 @@ const VueyeGrid = defineComponent({
387
475
  let binding;
388
476
  const table = useDataTable({
389
477
  ...expansionOptions(props, !!slots.expanded),
478
+ ...editingOptions(props),
390
479
  data: () => props.data,
391
480
  source: computed(() => props.source),
392
481
  loadMore: computed(() => props.loadMore),
@@ -395,6 +484,8 @@ const VueyeGrid = defineComponent({
395
484
  rowCount: () => props.rowCount,
396
485
  columns,
397
486
  rowKey: props.rowKey,
487
+ locale: props.locale ?? inherited().locale,
488
+ normalizeText: props.normalizeText,
398
489
  paginate: props.paginate ?? (props.source || props.loadMore ? false : props.virtual ? props.pagination : true),
399
490
  selectionMode: "none",
400
491
  initialState: { pagination: initialPagination },
@@ -411,6 +502,7 @@ const VueyeGrid = defineComponent({
411
502
  },
412
503
  onEditIssues(issues) {
413
504
  emit("edit-error", issues);
505
+ emit("edit-issues", issues);
414
506
  },
415
507
  onDataChange(data, changes) {
416
508
  emit("update:data", data);
@@ -435,7 +527,7 @@ const VueyeGrid = defineComponent({
435
527
  ...cellProps,
436
528
  render: cellSlot
437
529
  }) : cellProps.display;
438
- }
530
+ } else if (name.startsWith("editor.")) forwarded[name] = slot;
439
531
  return forwarded;
440
532
  };
441
533
  const button = (label, disabled, onClick) => h("button", {
@@ -448,20 +540,27 @@ const VueyeGrid = defineComponent({
448
540
  class: "vt-theme vueye-grid",
449
541
  "data-vt-theme": props.theme
450
542
  }, [
451
- props.toolbar || props.searchable ? h(VtToolbar, () => [
452
- props.searchable ? h(VtSearch, { placeholder: props.searchPlaceholder }) : null,
543
+ props.toolbar || props.searchable || props.addRow ? h(VtToolbar, () => [
544
+ props.searchable ? h(VtSearch, { placeholder: props.searchPlaceholder ?? locale().messages.searchPlaceholder }) : null,
545
+ props.addRow ? button(locale().messages.addRow, false, () => {
546
+ table.insertRows();
547
+ }) : null,
453
548
  h("div", { class: "vt-toolbar-spacer" }),
454
549
  props.toolbar ? [
455
- button("Undo", !table.canUndo, () => table.undo()),
456
- button("Redo", !table.canRedo, () => table.redo()),
457
- button("Export CSV", false, () => emit("export", table.exportRows()))
550
+ button(locale().messages.undo, !table.canUndo, () => table.undo()),
551
+ button(locale().messages.redo, !table.canRedo, () => table.redo()),
552
+ button(locale().messages.exportCsv, false, () => emit("export", table.exportRows()))
458
553
  ] : null
459
554
  ]) : null,
460
555
  h(VtGrid, {
461
556
  table,
462
- label: props.label,
557
+ label: props.label ?? locale().messages.spreadsheet,
463
558
  "aria-describedby": attrs["aria-describedby"],
464
559
  rowNumbers: props.rowNumbers,
560
+ rowActions: props.editable || props.removeRows,
561
+ removable: props.removeRows,
562
+ onSave: (result) => emit("save", result),
563
+ onCancel: (key) => emit("cancel", key),
465
564
  columnLetters: props.columnLetters,
466
565
  density: props.density,
467
566
  striped: props.striped,
@@ -498,12 +597,17 @@ const VueyeGrid = defineComponent({
498
597
  */
499
598
  const VueyeTable = defineComponent({
500
599
  name: "VueyeTable",
600
+ inheritAttrs: false,
501
601
  props: {
502
602
  data: {
503
603
  type: Array,
504
604
  default: () => []
505
605
  },
506
606
  ...commonProps,
607
+ editMode: {
608
+ type: String,
609
+ default: void 0
610
+ },
507
611
  /** `true` or `"multiple"` for checkboxes, `"single"` for one row at a time. */
508
612
  selectable: {
509
613
  type: [Boolean, String],
@@ -517,18 +621,25 @@ const VueyeTable = defineComponent({
517
621
  /** Shown instead of the empty state while `loading` and there are no rows yet. */
518
622
  loadingText: {
519
623
  type: String,
520
- default: "Loading…"
624
+ default: void 0
521
625
  }
522
626
  },
523
627
  emits: {
524
- ...Object.fromEntries(stateEmits.map((name) => [name, null])),
628
+ ...editingEmits,
629
+ ...stateEmitValidators,
525
630
  "state-change": (_state) => true,
526
631
  "row-click": (_item, _row) => true,
527
632
  expand: (_item, _row) => true,
528
633
  collapse: (_item, _row) => true
529
634
  },
530
635
  slots: Object,
531
- setup(props, { emit, slots, expose }) {
636
+ setup(props, { emit, slots, expose, attrs }) {
637
+ const inherited = useTableLocale();
638
+ const locale = provideTableLocale(() => ({
639
+ locale: props.locale,
640
+ messages: props.messages
641
+ }));
642
+ const loadingText = () => props.loadingText ?? locale().messages.loading;
532
643
  const selectionMode = computed(() => props.selectable === false ? "none" : props.selectable === "single" ? "single" : "multiple");
533
644
  const initialPagination = {
534
645
  page: props.page ?? 1,
@@ -538,18 +649,29 @@ const VueyeTable = defineComponent({
538
649
  let binding;
539
650
  const table = useDataTable({
540
651
  ...expansionOptions(props, !!slots.expanded),
652
+ ...editingOptions(props),
541
653
  data: () => props.data,
542
654
  source: computed(() => props.source),
543
655
  loadMore: computed(() => props.loadMore),
544
656
  endThreshold: props.endThreshold,
545
657
  columns: () => resolveColumns(props.columns, props.data),
546
658
  rowKey: props.rowKey,
659
+ locale: props.locale ?? inherited().locale,
660
+ normalizeText: props.normalizeText,
547
661
  manual: props.manual,
548
662
  paginate: props.paginate ?? !(props.virtual || props.source || props.loadMore),
549
663
  rowCount: () => props.rowCount,
550
664
  selectionMode: selectionMode.value,
551
665
  selectScope: props.selectScope,
552
666
  initialState: { pagination: initialPagination },
667
+ onDataChange(data, changes) {
668
+ emit("update:data", data);
669
+ emit("edit", changes);
670
+ },
671
+ onEditIssues(issues) {
672
+ emit("edit-issues", issues);
673
+ emit("edit-error", issues);
674
+ },
553
675
  state: () => controlledState(props, binding?.table.getState().pagination ?? initialPagination),
554
676
  onStateChange(state, previous) {
555
677
  emitStateChanges(emit, state, previous);
@@ -562,15 +684,21 @@ const VueyeTable = defineComponent({
562
684
  expose({ table });
563
685
  const busy = () => props.loading || table.loadState === "loading" || table.loadState === "streaming";
564
686
  const selectable = () => selectionMode.value !== "none";
565
- const cell = (row, column) => {
687
+ const cell = (row, column, rowIndex) => {
566
688
  const slot = slots[`cell.${column.id}`];
567
689
  const treeCell = table.tree && column.id === resolveTreeColumn(table, props.treeColumn);
568
- return h(DataTableCell, {
690
+ return h(props.editMode ? DataTableEditCell : DataTableCell, {
569
691
  key: column.id,
570
692
  row,
571
693
  column,
572
- tree: false
694
+ tree: false,
695
+ ...props.editMode ? {
696
+ rowIndex,
697
+ onSave: (result) => emit("save", result),
698
+ onCancel: (key) => emit("cancel", key)
699
+ } : {}
573
700
  }, {
701
+ editor: slots[`editor.${column.id}`],
574
702
  default: ({ value, display }) => {
575
703
  const content = () => slot ? h(CellContent, {
576
704
  row,
@@ -585,22 +713,37 @@ const VueyeTable = defineComponent({
585
713
  });
586
714
  };
587
715
  const hasDetails = () => !!slots.expanded && !table.tree;
588
- const width = () => table.columns.length + (selectable() ? 1 : 0) + (hasDetails() ? 1 : 0);
716
+ const hasActions = () => !!props.editMode || props.removeRows;
717
+ const leadingColumns = () => Number(hasActions()) + Number(hasDetails()) + Number(selectable());
718
+ const width = () => table.columns.length + (selectable() ? 1 : 0) + (hasDetails() ? 1 : 0) + (hasActions() ? 1 : 0);
589
719
  const emptyBody = () => {
590
720
  if (table.rows.length === 0) {
591
- const content = busy() ? slots.loading?.({}) ?? h(VtEmpty, { text: props.loadingText }) : slots.empty?.({}) ?? h(VtEmpty, { text: table.loadingMode && table.loadState === "error" ? "Could not load rows." : "No matching rows" });
721
+ const content = busy() ? slots.loading?.({}) ?? h(VtEmpty, { text: loadingText() }) : slots.empty?.({}) ?? h(VtEmpty, { text: table.loadingMode && table.loadState === "error" ? locale().messages.couldNotLoadRows : locale().messages.noMatchingRows });
592
722
  return h("tr", { "data-empty": "" }, [h("td", { colspan: Math.max(1, width()) }, content)]);
593
723
  }
594
724
  return null;
595
725
  };
596
- const cells = (row) => {
726
+ const cells = (row, rowIndex) => {
597
727
  return [
598
- hasDetails() ? h("td", { class: "vt-expansion-cell" }, [h(VtExpandToggle, { row })]) : null,
728
+ hasActions() ? h("td", {
729
+ class: "vt-row-controls",
730
+ "aria-colindex": 1,
731
+ onClick: (event) => event.stopPropagation()
732
+ }, [h(VtRowActions, {
733
+ row,
734
+ editable: props.editMode === "row",
735
+ removable: props.removeRows
736
+ })]) : null,
737
+ hasDetails() ? h("td", {
738
+ class: "vt-expansion-cell",
739
+ "aria-colindex": Number(hasActions()) + 1
740
+ }, [h(VtExpandToggle, { row })]) : null,
599
741
  selectable() ? h("td", {
600
742
  class: "vt-selection-cell",
743
+ "aria-colindex": Number(hasActions()) + Number(hasDetails()) + 1,
601
744
  onClick: (event) => event.stopPropagation()
602
745
  }, [h(DataTableSelectRow, { row })]) : null,
603
- ...table.columns.map((column) => cell(row, column))
746
+ ...table.columns.map((column) => cell(row, column, rowIndex))
604
747
  ];
605
748
  };
606
749
  const bodyRow = ({ row, rowIndex }) => h(DataTableRow, {
@@ -609,25 +752,30 @@ const VueyeTable = defineComponent({
609
752
  rowIndex,
610
753
  onClick: () => emit("row-click", row.original, row)
611
754
  }, {
612
- default: () => cells(row),
755
+ default: () => cells(row, rowIndex),
613
756
  $stable: true
614
757
  });
615
758
  const headerSlots = () => {
616
- const forwarded = {};
617
- for (const column of table.columns) {
618
- const slot = slots[`header.${column.id}`];
619
- if (slot) forwarded[`header.${column.id}`] = () => slot({ column });
620
- }
621
759
  return {
622
- ...forwarded,
623
- before: () => [hasDetails() ? h("th", {
624
- class: "vt-expansion-cell",
625
- scope: "col",
626
- "aria-label": "Details"
627
- }) : null, selectable() ? h("th", {
628
- class: "vt-selection-cell",
629
- scope: "col"
630
- }, selectionMode.value === "multiple" ? [h(DataTableSelectAll)] : []) : null]
760
+ header: (header) => slots[`header.${header.column.id}`]?.(header) ?? header.column.header,
761
+ before: () => [
762
+ hasActions() ? h("th", {
763
+ class: "vt-row-controls",
764
+ scope: "col",
765
+ "aria-colindex": 1
766
+ }, locale().messages.rowActions) : null,
767
+ hasDetails() ? h("th", {
768
+ class: "vt-expansion-cell",
769
+ scope: "col",
770
+ "aria-colindex": Number(hasActions()) + 1,
771
+ "aria-label": locale().messages.details
772
+ }) : null,
773
+ selectable() ? h("th", {
774
+ class: "vt-selection-cell",
775
+ scope: "col",
776
+ "aria-colindex": Number(hasActions()) + Number(hasDetails()) + 1
777
+ }, selectionMode.value === "multiple" ? [h(DataTableSelectAll)] : []) : null
778
+ ]
631
779
  };
632
780
  };
633
781
  const tableContent = () => {
@@ -650,6 +798,7 @@ const VueyeTable = defineComponent({
650
798
  }, { default: () => h(DataTableRoot, {
651
799
  table,
652
800
  class: "vt-table",
801
+ leadingColumns: leadingColumns(),
653
802
  virtual: props.virtual,
654
803
  rowHeight: props.rowHeight,
655
804
  overscan: props.overscan,
@@ -660,11 +809,11 @@ const VueyeTable = defineComponent({
660
809
  treeColumn: props.treeColumn,
661
810
  keepAliveDetail: props.keepAliveDetail,
662
811
  class: "vt-table",
663
- "aria-colcount": table.columns.length,
812
+ leadingColumns: leadingColumns(),
664
813
  "aria-busy": busy() ? "true" : void 0
665
814
  }, children)]);
666
815
  };
667
- return () => h("div", {
816
+ const surface = () => h("div", mergeProps(attrs, {
668
817
  class: "vt-surface vueye-table",
669
818
  "data-density": props.density,
670
819
  "data-striped": props.striped ? "" : void 0,
@@ -676,9 +825,14 @@ const VueyeTable = defineComponent({
676
825
  "data-vt-theme": props.theme,
677
826
  "aria-busy": props.loading ? "true" : void 0,
678
827
  style: props.maxHeight ? { "--vt-max-height": props.maxHeight } : void 0
679
- }, [h("div", { class: "vt-root" }, [
680
- props.searchable || props.columnToggle || slots.toolbar ? h(VtToolbar, () => [
681
- props.searchable ? h(VtSearch, { placeholder: props.searchPlaceholder }) : null,
828
+ }), [h("div", { class: "vt-root" }, [
829
+ props.searchable || props.columnToggle || slots.toolbar || props.addRow ? h(VtToolbar, () => [
830
+ props.searchable ? h(VtSearch, { placeholder: props.searchPlaceholder ?? locale().messages.searchPlaceholder }) : null,
831
+ props.addRow ? h("button", {
832
+ type: "button",
833
+ class: "vt-button",
834
+ onClick: () => table.insertRows()
835
+ }, locale().messages.addRow) : null,
682
836
  h("div", { class: "vt-toolbar-spacer" }),
683
837
  slots.toolbar?.({ table }),
684
838
  props.columnToggle ? h(VtColumnVisibility) : null
@@ -689,21 +843,37 @@ const VueyeTable = defineComponent({
689
843
  }),
690
844
  tableContent(),
691
845
  props.pagination && (!props.virtual || table.paginate) || slots.footer || slots.status || table.tree || table.loadingMode ? h(VtToolbar, { class: "vt-footer" }, () => [
692
- h(VtStatus, null, slots.status ? { default: (status) => slots.status?.(status) } : props.loading && table.rows.length === 0 ? { default: () => props.loadingText } : void 0),
846
+ h(VtStatus, null, slots.status ? { default: (status) => slots.status?.(status) } : props.loading && table.rows.length === 0 ? { default: () => loadingText() } : void 0),
693
847
  ...table.loadingMode ? [h(VtLoadMore)] : [],
694
848
  slots.footer?.({ table }),
695
849
  props.pagination && table.paginate && (!props.virtual || table.paginate) ? h("div", { class: "vt-footer-controls" }, [h(VtPageSize, { options: props.pageSizeOptions }), h(VtPagination)]) : null
696
850
  ]) : null
697
851
  ])]);
852
+ return () => props.editMode ? h(DataTableEditRoot, {
853
+ table,
854
+ mode: props.editMode,
855
+ onSave: (result) => emit("save", result),
856
+ onCancel: (key) => emit("cancel", key)
857
+ }, surface) : surface();
698
858
  }
699
859
  });
700
860
 
701
861
  //#endregion
702
862
  //#region src/plugin.ts
703
- /** Register `<VueyeTable>` and `<VueyeGrid>` globally. */
704
- const VueyeTablePlugin = { install(app) {
863
+ /**
864
+ * Register `<VueyeTable>` and `<VueyeGrid>` globally. A `locale` and `messages` given here are
865
+ * the default of every table in the application; a table's own props win over them.
866
+ */
867
+ const VueyeTablePlugin = { install(app, options) {
705
868
  app.component("VueyeTable", VueyeTable);
706
869
  app.component("VueyeGrid", VueyeGrid);
870
+ if (options?.locale !== void 0 || options?.messages !== void 0) {
871
+ const language = {
872
+ locale: options.locale,
873
+ messages: options.messages
874
+ };
875
+ app.provide(tableLocaleKey, () => language);
876
+ }
707
877
  } };
708
878
 
709
879
  //#endregion