@shwfed/nuxt 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shwfed/nuxt",
3
3
  "configKey": "shwfed",
4
- "version": "0.1.16",
4
+ "version": "0.1.17",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -1,5 +1,13 @@
1
1
  <script setup>
2
+ import { useHead } from "#app";
2
3
  import { Tooltip } from "reka-ui/namespaced";
4
+ useHead({
5
+ bodyAttrs: {
6
+ style: {
7
+ "--primary": "#2DA8BC"
8
+ }
9
+ }
10
+ });
3
11
  </script>
4
12
 
5
13
  <template>
@@ -1,5 +1,9 @@
1
1
  import type { RowData, TableOptions } from '@tanstack/vue-table';
2
2
  export type Expression = string;
3
+ export type Render = string | Readonly<{
4
+ id: string;
5
+ props: unknown;
6
+ }>;
3
7
  export type Accessor = string | Readonly<{
4
8
  read: Expression;
5
9
  write: Expression;
@@ -9,10 +13,7 @@ export type Column = Readonly<{
9
13
  title?: string;
10
14
  accessor?: Accessor;
11
15
  accessorKey?: string;
12
- renderer?: string | Readonly<{
13
- id: string;
14
- props: unknown;
15
- }>;
16
+ renderer?: Render;
16
17
  tooltip?: string;
17
18
  size?: number;
18
19
  enableSorting?: boolean;
@@ -6,7 +6,6 @@ import { getProperty } from "dot-prop";
6
6
  import { Pagination } from "reka-ui/namespaced";
7
7
  import { computed, ref } from "vue";
8
8
  import { useNuxtApp } from "#app";
9
- import { useCheating } from "../composables/useCheating";
10
9
  import { useTableRenderers } from "../composables/useTableRenderers";
11
10
  import Tooltip from "./tooltip.vue";
12
11
  </script>
@@ -23,7 +22,6 @@ const props = defineProps({
23
22
  cellStyles: { type: String, required: false, default: void 0 },
24
23
  props: { type: Object, required: false, default: void 0 }
25
24
  });
26
- const isCheating = useCheating();
27
25
  const { $dsl, $markdown } = useNuxtApp();
28
26
  const { resolveTableRenderer } = useTableRenderers();
29
27
  const containerRef = ref(null);
@@ -39,29 +37,10 @@ function genColumnId(column) {
39
37
  return crypto.randomUUID();
40
38
  }
41
39
  function translate(column) {
42
- const rendererId = typeof column.renderer === "string" ? column.renderer : column.renderer?.id ? column.renderer.id : "table.renderer.text";
43
- const rendererProps = column.renderer && typeof column.renderer === "object" && "props" in column.renderer ? column.renderer.props : null;
44
- const renderer = resolveTableRenderer(rendererId);
45
- const options = renderer.parseOptions(rendererProps);
46
- const helpers = {
47
- renderInline,
48
- evaluate: $dsl.evaluate
49
- };
50
- const header = (ctx) => {
51
- if (renderer.header) {
52
- return renderer.header({
53
- ctx,
54
- title: typeof column.title === "string" ? column.title : void 0,
55
- options,
56
- helpers
57
- });
58
- }
59
- return typeof column.title === "string" ? column.title : void 0;
60
- };
61
40
  if (Array.isArray(column.columns) && column.columns.length > 0) {
62
41
  return {
63
42
  id: column.id ?? genColumnId(column),
64
- header,
43
+ header: column.title,
65
44
  columns: column.columns?.map((column2) => translate(column2)) ?? [],
66
45
  enableSorting: column.enableSorting ?? false,
67
46
  enableMultiSort: column.enableMultiSorting,
@@ -73,13 +52,14 @@ function translate(column) {
73
52
  }
74
53
  };
75
54
  }
76
- const cell = (ctx) => {
77
- return renderer.cell({ ctx, options, helpers });
78
- };
55
+ const renderer = resolveTableRenderer(typeof column.renderer === "string" ? column.renderer : column.renderer?.id ? column.renderer.id : "table.renderer.text");
56
+ const options = renderer.parseOptions(column.renderer && typeof column.renderer === "object" && "props" in column.renderer ? column.renderer.props : null);
79
57
  return {
80
58
  id: column.id ?? genColumnId(column),
81
- header,
82
- cell,
59
+ header: (ctx) => renderer.header?.({ ctx, options }) ?? column.title,
60
+ cell: (ctx) => {
61
+ return renderer.cell({ ctx, options });
62
+ },
83
63
  accessorFn: (row, index) => {
84
64
  const key = column.accessorKey ? column.accessorKey : column.accessor;
85
65
  if (typeof key === "string") {
@@ -224,15 +204,24 @@ function getCellStyles(ctx) {
224
204
  return {};
225
205
  }
226
206
  }
227
- function hasAdjacentColumns(column) {
207
+ function shouldHaveRightBorder(column) {
228
208
  switch (column.getIsPinned()) {
229
209
  case "left":
230
- return !column.getIsLastColumn("left");
231
- // why would anyone pin all columns to the left?
210
+ return true;
232
211
  case "right":
233
212
  return !column.getIsLastColumn("right");
234
213
  case false:
235
- return !column.getIsLastColumn("center") || table.getIsSomeColumnsPinned("right");
214
+ return !column.getIsLastColumn("center");
215
+ }
216
+ }
217
+ function shouldHaveLeftBorder(column) {
218
+ switch (column.getIsPinned()) {
219
+ case "left":
220
+ return false;
221
+ case "right":
222
+ return true;
223
+ case false:
224
+ return false;
236
225
  }
237
226
  }
238
227
  function pinnedStyle(column) {
@@ -263,11 +252,10 @@ function getSortIcon(column) {
263
252
  <template>
264
253
  <div
265
254
  class="flex flex-col h-full"
266
- :style="isCheating ? { '--primary': '#BC1111' } : { '--primary': '#2DA8BC' }"
267
255
  >
268
256
  <div
269
257
  ref="containerRef"
270
- class="overflow-scroll flex-1 border border-zinc-200 rounded relative"
258
+ class="overflow-scroll overscroll-none flex-1 border border-zinc-200 rounded relative"
271
259
  >
272
260
  <div :style="{ height: `${rowTotalSize}px` }">
273
261
  <table class="grid">
@@ -287,7 +275,8 @@ function getSortIcon(column) {
287
275
  'text-xs flex items-center justify-center relative',
288
276
  'bg-[color-mix(in_srgb,var(--primary)_10%,white)] group',
289
277
  header.column.getIsPinned() && 'sticky z-15',
290
- (header.column.getIsPinned() === 'left' || hasAdjacentColumns(header.column)) && 'border-r'
278
+ shouldHaveRightBorder(header.column) && 'border-r',
279
+ shouldHaveLeftBorder(header.column) && 'border-l'
291
280
  ]"
292
281
  :style="{
293
282
  width: `${header.getSize()}px`,
@@ -354,7 +343,7 @@ function getSortIcon(column) {
354
343
  v-for="r in rowWindow"
355
344
  :key="rows[r.index]?.id ?? r.index"
356
345
  :ref="measureRow"
357
- class="flex absolute w-full"
346
+ class="flex absolute w-full not-last:border-b border-zinc-300"
358
347
  :data-index="rows[r.index]?.index"
359
348
  :style="{ transform: `translate3d(0, ${r.start}px, 0)` }"
360
349
  >
@@ -362,10 +351,11 @@ function getSortIcon(column) {
362
351
  v-for="cell in rows[r.index]?.getVisibleCells() ?? []"
363
352
  :key="cell.id"
364
353
  :class="[
365
- 'border-b border-zinc-300',
354
+ 'border-zinc-300',
366
355
  cell.column.columnDef.meta?.grow && 'flex-1',
367
356
  cell.column.getIsPinned() && 'sticky z-15',
368
- (cell.column.getIsPinned() === 'left' || hasAdjacentColumns(cell.column)) && 'border-r'
357
+ shouldHaveRightBorder(cell.column) && 'border-r',
358
+ shouldHaveLeftBorder(cell.column) && 'border-l'
369
359
  ]"
370
360
  :style="{
371
361
  width: `${cell.column.getSize()}px`,
@@ -380,6 +370,39 @@ function getSortIcon(column) {
380
370
  </td>
381
371
  </tr>
382
372
  </tbody>
373
+
374
+ <tfoot class="hidden has-[[data-footer]]:grid sticky bottom-0 z-10 select-none border-t border-zinc-200">
375
+ <tr
376
+ v-for="group in table.getFooterGroups()"
377
+ :key="group.id"
378
+ class="flex w-full border-zinc-200"
379
+ >
380
+ <th
381
+ v-for="header in group.headers"
382
+ :key="header.id"
383
+ :colSpan="header.colSpan"
384
+ :class="[
385
+ header.column.columnDef.meta?.grow && 'flex-1',
386
+ 'flex items-center gap-2 border-zinc-300 text-zinc-600 p-0',
387
+ 'text-xs flex items-center justify-center relative',
388
+ 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] group',
389
+ header.column.getIsPinned() && 'sticky z-15',
390
+ shouldHaveRightBorder(header.column) && 'border-r',
391
+ shouldHaveLeftBorder(header.column) && 'border-l'
392
+ ]"
393
+ :style="{
394
+ width: `${header.getSize()}px`,
395
+ ...pinnedStyle(header.column)
396
+ }"
397
+ >
398
+ <FlexRender
399
+ v-if="!header.isPlaceholder"
400
+ :render="header.column.columnDef.footer"
401
+ :props="header.getContext()"
402
+ />
403
+ </th>
404
+ </tr>
405
+ </tfoot>
383
406
  </table>
384
407
  </div>
385
408
  </div>
@@ -1,5 +1,9 @@
1
1
  import type { RowData, TableOptions } from '@tanstack/vue-table';
2
2
  export type Expression = string;
3
+ export type Render = string | Readonly<{
4
+ id: string;
5
+ props: unknown;
6
+ }>;
3
7
  export type Accessor = string | Readonly<{
4
8
  read: Expression;
5
9
  write: Expression;
@@ -9,10 +13,7 @@ export type Column = Readonly<{
9
13
  title?: string;
10
14
  accessor?: Accessor;
11
15
  accessorKey?: string;
12
- renderer?: string | Readonly<{
13
- id: string;
14
- props: unknown;
15
- }>;
16
+ renderer?: Render;
16
17
  tooltip?: string;
17
18
  size?: number;
18
19
  enableSorting?: boolean;
@@ -1,7 +1,7 @@
1
1
  import '../table-renderers/builtins.js';
2
2
  import { getTableRenderer, resolveTableRenderer } from '../table-renderers/registry.js';
3
3
  export { defineTableRenderer } from '../table-renderers/registry.js';
4
- export type { TableRenderer, TableRendererCellArgs, TableRendererColumnDefOverrides, TableRendererConfigComponent, TableRendererHeaderArgs, TableRendererId, } from '../table-renderers/registry.js';
4
+ export type { TableRenderer, TableRendererCellArgs, TableRendererColumnDefOverrides, TableRendererConfigComponent, TableRendererFooterArgs, TableRendererHeaderArgs, TableRendererId, } from '../table-renderers/registry.js';
5
5
  export declare function useTableRenderers(): {
6
6
  getTableRenderer: typeof getTableRenderer;
7
7
  resolveTableRenderer: typeof resolveTableRenderer;
@@ -4,6 +4,7 @@ import { format as formatDate, isValid, toDate } from "date-fns";
4
4
  import { defineComponent } from "vue";
5
5
  import { z } from "zod";
6
6
  import { defineTableRenderer } from "./registry.js";
7
+ import { useNuxtApp } from "#app";
7
8
  const JUSTIFY_CLASS = {
8
9
  left: "justify-start",
9
10
  center: "justify-center",
@@ -185,16 +186,17 @@ defineTableRenderer(
185
186
  align: z.enum(["left", "center", "right"]).default("left")
186
187
  },
187
188
  {
188
- cell: ({ ctx, options, helpers }) => {
189
+ cell: ({ ctx, options }) => {
189
190
  const rawValue = ctx.cell.getValue();
190
191
  const isEmpty = rawValue === void 0 || rawValue === null;
191
192
  const align = isEmpty ? "center" : options.align ?? "left";
192
193
  const justifyClass = JUSTIFY_CLASS[align];
194
+ const { $dsl } = useNuxtApp();
193
195
  const onCopy = async () => {
194
196
  try {
195
197
  let text = String(ctx.cell.getValue());
196
- if (options.copyExpression && helpers.evaluate) {
197
- text = String(helpers.evaluate(options.copyExpression, {
198
+ if (options.copyExpression) {
199
+ text = String($dsl.evaluate(options.copyExpression, {
198
200
  row: ctx.row.original,
199
201
  index: BigInt(ctx.row.index)
200
202
  }));
@@ -287,7 +289,7 @@ defineTableRenderer(
287
289
  type: "checkbox",
288
290
  checked,
289
291
  class: [
290
- "peer h-4 w-4 cursor-pointer transition-colors duration-180 appearance-none rounded",
292
+ "peer h-4 w-4 cursor-pointer transition-colors duration-180 appearance-none rounded bg-white",
291
293
  "border border-[color-mix(in_srgb,var(--primary)_10%,#00000033)] not-checked-group-hover:border-[color-mix(in_srgb,var(--primary)_20%,#00000033)]",
292
294
  "not-checked-group-hover:bg-[color-mix(in_srgb,var(--primary)_5%,#00000011)] checked:border-[var(--primary)] checked:bg-[var(--primary)]"
293
295
  ],
@@ -333,7 +335,10 @@ defineTableRenderer(
333
335
  children: /* @__PURE__ */ jsx(Icon, { icon: ctx.table.getIsAllRowsExpanded() ? "fluent:subtract-square-20-regular" : "fluent:add-square-20-regular" })
334
336
  }
335
337
  ) }),
336
- config: NoOptionsConfig
338
+ config: NoOptionsConfig,
339
+ columnDefOverrides: {
340
+ enableResizing: false
341
+ }
337
342
  }
338
343
  );
339
344
  defineTableRenderer(
@@ -394,9 +399,10 @@ defineTableRenderer(
394
399
  source: z.string().optional()
395
400
  },
396
401
  {
397
- cell: ({ ctx, options, helpers }) => {
402
+ cell: ({ ctx, options }) => {
403
+ const { $markdown } = useNuxtApp();
398
404
  const source = options.source ?? String(ctx.cell.getValue());
399
- const html = helpers.renderInline(source);
405
+ const html = $markdown.renderInline(source);
400
406
  return /* @__PURE__ */ jsx("div", { class: "relative w-full py-2 px-1 flex items-center justify-center text-xs", children: /* @__PURE__ */ jsx("span", { class: "prose prose-zinc text-xs", innerHTML: html }) });
401
407
  },
402
408
  config: TableRendererMarkdownConfig
@@ -6,19 +6,14 @@ export type TableRendererColumnDefOverrides<TData extends RowData = unknown> = P
6
6
  export type TableRendererCellArgs<TData extends RowData, TValue, TOptions> = Readonly<{
7
7
  ctx: CellContext<TData, TValue>;
8
8
  options: TOptions;
9
- helpers: Readonly<{
10
- renderInline: (source: string) => string;
11
- evaluate?: (source: string, context?: Record<string, unknown>) => unknown;
12
- }>;
13
9
  }>;
14
10
  export type TableRendererHeaderArgs<TData extends RowData, TValue, TOptions> = Readonly<{
15
11
  ctx: HeaderContext<TData, TValue>;
16
- title?: string;
17
12
  options: TOptions;
18
- helpers: Readonly<{
19
- renderInline: (source: string) => string;
20
- evaluate?: (source: string, context?: Record<string, unknown>) => unknown;
21
- }>;
13
+ }>;
14
+ export type TableRendererFooterArgs<TData extends RowData, TValue, TOptions> = Readonly<{
15
+ ctx: HeaderContext<TData, TValue>;
16
+ options: TOptions;
22
17
  }>;
23
18
  export type TableRendererConfigComponent<_TOptions> = unknown;
24
19
  export type TableRenderer<TOptions> = Readonly<{
@@ -27,12 +22,14 @@ export type TableRenderer<TOptions> = Readonly<{
27
22
  parseOptions: (input: unknown) => TOptions;
28
23
  cell: (args: TableRendererCellArgs<unknown, unknown, TOptions>) => VNodeChild;
29
24
  header?: (args: TableRendererHeaderArgs<unknown, unknown, TOptions>) => VNodeChild;
25
+ footer?: (args: TableRendererFooterArgs<unknown, unknown, TOptions>) => VNodeChild;
30
26
  config?: TableRendererConfigComponent<TOptions>;
31
27
  columnDefOverrides?: TableRendererColumnDefOverrides;
32
28
  }>;
33
29
  export declare function defineTableRenderer<const TShape extends z.ZodRawShape, const TOptions = z.infer<z.ZodObject<TShape>>>(id: TableRendererId, shape: TShape, impl: Readonly<{
34
30
  cell: TableRenderer<TOptions>['cell'];
35
31
  header?: TableRenderer<TOptions>['header'];
32
+ footer?: TableRenderer<TOptions>['footer'];
36
33
  config?: TableRenderer<TOptions>['config'];
37
34
  columnDefOverrides?: TableRenderer<TOptions>['columnDefOverrides'];
38
35
  }>): TableRenderer<TOptions>;
@@ -6,11 +6,12 @@ export function defineTableRenderer(id, shape, impl) {
6
6
  id,
7
7
  optionsSchema,
8
8
  parseOptions: (input) => {
9
- const normalized = input == null ? {} : input;
9
+ const normalized = input === null || input === void 0 ? {} : input;
10
10
  return optionsSchema.parse(normalized);
11
11
  },
12
12
  cell: impl.cell,
13
13
  header: impl.header,
14
+ footer: impl.footer,
14
15
  config: impl.config,
15
16
  columnDefOverrides: impl.columnDefOverrides
16
17
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shwfed/nuxt",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "type": "module",