@shwfed/nuxt 0.11.21 → 0.11.23

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.11.21",
4
+ "version": "0.11.23",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -63,12 +63,34 @@ function cloneConfig(config2) {
63
63
  function getConfigOrientation(config2) {
64
64
  return config2.orientation ?? "horizontal";
65
65
  }
66
+ function tryEvaluateExpression(source, context) {
67
+ try {
68
+ return {
69
+ ok: true,
70
+ value: $dsl.evaluate`${source}`(context)
71
+ };
72
+ } catch {
73
+ return {
74
+ ok: false
75
+ };
76
+ }
77
+ }
78
+ function evaluateExpression(source, context, fallback) {
79
+ const result = tryEvaluateExpression(source, context);
80
+ if (!result.ok) {
81
+ return fallback;
82
+ }
83
+ return result.value;
84
+ }
66
85
  function getConfigStyle(config2) {
67
86
  const style = {};
68
87
  if (!config2.style) {
69
88
  return style;
70
89
  }
71
- const styleMap = $dsl.evaluate`${config2.style}`({ form: modelValue.value });
90
+ const styleMap = evaluateExpression(config2.style, { form: modelValue.value }, {});
91
+ if (!styleMap || typeof styleMap !== "object" || Array.isArray(styleMap)) {
92
+ return style;
93
+ }
72
94
  for (const [key, value] of Object.entries(styleMap)) {
73
95
  if (typeof value === "string" || typeof value === "number") {
74
96
  Reflect.set(style, key, value);
@@ -80,7 +102,7 @@ function getFieldStyle(field) {
80
102
  if (!field.style) {
81
103
  return {};
82
104
  }
83
- const style = $dsl.evaluate`${field.style}`();
105
+ const style = evaluateExpression(field.style, void 0, {});
84
106
  const normalizedStyle = {};
85
107
  if (!style || typeof style !== "object" || Array.isArray(style)) {
86
108
  return normalizedStyle;
@@ -109,10 +131,10 @@ function displayCalendarValue(stored, displayFormat, valueFormat) {
109
131
  return stored ?? "";
110
132
  }
111
133
  function isFieldHidden(field) {
112
- return $dsl.evaluate`${field.hidden || "false"}`({ form: modelValue.value });
134
+ return evaluateExpression(field.hidden || "false", { form: modelValue.value }, false);
113
135
  }
114
136
  function isFieldDisabled(field) {
115
- return $dsl.evaluate`${field.disabled || "false"}`({ form: modelValue.value });
137
+ return evaluateExpression(field.disabled || "false", { form: modelValue.value }, false);
116
138
  }
117
139
  function getFieldValue(field) {
118
140
  return getProperty(modelValue.value, field.path);
@@ -122,7 +144,11 @@ function initializeFieldValues(config2) {
122
144
  if (isPassiveField(field) || !field.initialValue || hasProperty(modelValue.value, field.path)) {
123
145
  continue;
124
146
  }
125
- const initialValue = $dsl.evaluate`${field.initialValue}`({ form: modelValue.value });
147
+ const initialValueResult = tryEvaluateExpression(field.initialValue, { form: modelValue.value });
148
+ if (!initialValueResult.ok) {
149
+ continue;
150
+ }
151
+ const initialValue = initialValueResult.value;
126
152
  setProperty(
127
153
  modelValue.value,
128
154
  field.path,
@@ -155,12 +181,22 @@ function isSelectValueEqual(left, right) {
155
181
  return leftValue === rightValue;
156
182
  }
157
183
  function getSelectOptions(field) {
158
- return $dsl.evaluate`${field.options}`().map((option) => {
159
- return {
160
- key: $dsl.evaluate`${field.key}`({ option }),
161
- label: $dsl.evaluate`${field.label}`({ option }),
162
- value: $dsl.evaluate`${field.value}`({ option })
163
- };
184
+ const options = evaluateExpression(field.options, void 0, []);
185
+ if (!Array.isArray(options)) {
186
+ return [];
187
+ }
188
+ return options.flatMap((option) => {
189
+ const key = tryEvaluateExpression(field.key, { option });
190
+ const label = tryEvaluateExpression(field.label, { option });
191
+ const value = tryEvaluateExpression(field.value, { option });
192
+ if (!key.ok || !label.ok || !value.ok) {
193
+ return [];
194
+ }
195
+ return [{
196
+ key: key.value,
197
+ label: label.value,
198
+ value: value.value
199
+ }];
164
200
  });
165
201
  }
166
202
  function getSelectFieldState(field) {
@@ -251,7 +287,11 @@ function getValidationFailure(field) {
251
287
  form: modelValue.value
252
288
  };
253
289
  for (const rule of field.validation) {
254
- if (!$dsl.evaluate`${rule.expression}`(context)) {
290
+ const evaluation = tryEvaluateExpression(rule.expression, context);
291
+ if (!evaluation.ok) {
292
+ continue;
293
+ }
294
+ if (!evaluation.value) {
255
295
  return {
256
296
  message: rule.message,
257
297
  context: snapshotValidationContext(field)
@@ -300,6 +340,16 @@ function renderValidationMessage(field) {
300
340
  if (!error) return "";
301
341
  return $md.inline`${error.message}`(error.context);
302
342
  }
343
+ function isCalendarDateDisabled(field, date) {
344
+ if (!field.disableDate) {
345
+ return false;
346
+ }
347
+ return evaluateExpression(
348
+ field.disableDate,
349
+ { date: new TZDate(date.toDate(getLocalTimeZone())) },
350
+ false
351
+ );
352
+ }
303
353
  function handleCalendarOpenChange(field, open) {
304
354
  if (open) {
305
355
  calendarOpen.value[field.path] = true;
@@ -512,7 +562,7 @@ export {
512
562
  :layout="field.mode"
513
563
  :model-value="toCalendarDateValue(getProperty(modelValue, field.path), field.value)"
514
564
  :disabled="isFieldDisabled(field)"
515
- :is-date-disabled="field.disableDate ? (date) => !!$dsl.evaluate`${field.disableDate}`({ date: new TZDate(date.toDate(getLocalTimeZone())) }) : void 0"
565
+ :is-date-disabled="field.disableDate ? (date) => isCalendarDateDisabled(field, date) : void 0"
516
566
  @update:model-value="(value) => {
517
567
  if (value === void 0) {
518
568
  deleteProperty(modelValue, field.path);
@@ -6,6 +6,7 @@ import { computedAsync } from "@vueuse/core";
6
6
  import { Effect } from "effect";
7
7
  import { computed, ref, watch } from "vue";
8
8
  import { useI18n } from "vue-i18n";
9
+ import { mergeDslContexts, useCELContext } from "../../../plugins/cel/context";
9
10
  import { getLocalizedText } from "../../../utils/coders";
10
11
  import { Button } from "../button";
11
12
  import { Skeleton } from "../skeleton";
@@ -22,7 +23,9 @@ const displayConfig = ref(defaultConfig);
22
23
  const { $dsl, $md } = useNuxtApp();
23
24
  const { t, locale } = useI18n();
24
25
  const isCheating = useCheating();
26
+ const inheritedContext = useCELContext();
25
27
  const isConfiguratorOpen = ref(false);
28
+ const resolvedContext = computed(() => mergeDslContexts(props.context, inheritedContext));
26
29
  function normalizeStyle(value) {
27
30
  const style = {};
28
31
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -40,7 +43,7 @@ const renderedStyle = computed(() => {
40
43
  return {};
41
44
  }
42
45
  try {
43
- return normalizeStyle($dsl.evaluate`${displayConfig.value.style}`(props.context ?? {}));
46
+ return normalizeStyle($dsl.evaluate`${displayConfig.value.style}`(resolvedContext.value));
44
47
  } catch {
45
48
  return {};
46
49
  }
@@ -51,9 +54,9 @@ const renderedMarkdown = computed(() => {
51
54
  return "";
52
55
  }
53
56
  if (displayConfig.value.inline) {
54
- return $md.inline`${markdownSource.value}`(props.context);
57
+ return $md.inline`${markdownSource.value}`(resolvedContext.value);
55
58
  }
56
- return $md.block`${markdownSource.value}`(props.context);
59
+ return $md.block`${markdownSource.value}`(resolvedContext.value);
57
60
  });
58
61
  function handleConfiguratorConfirm(nextConfig) {
59
62
  displayConfig.value = nextConfig;
@@ -107,7 +110,7 @@ export {
107
110
  v-if="resolvedConfig !== void 0"
108
111
  v-model:open="isConfiguratorOpen"
109
112
  :config="displayConfig"
110
- :context="props.context"
113
+ :context="resolvedContext"
111
114
  @confirm="handleConfiguratorConfirm"
112
115
  />
113
116
 
@@ -6,6 +6,7 @@ import { computedAsync } from "@vueuse/core";
6
6
  import { Effect } from "effect";
7
7
  import { computed, nextTick, onMounted, onUnmounted, ref, watch } from "vue";
8
8
  import { useI18n } from "vue-i18n";
9
+ import { mergeDslContexts, useCELContext } from "../../../plugins/cel/context";
9
10
  import { getLocalizedText } from "../../../utils/coders";
10
11
  import { Button } from "../button";
11
12
  import MenuTabsConfiguratorDialog from "../menu-tabs-configurator/MenuTabsConfiguratorDialog.vue";
@@ -27,6 +28,7 @@ const route = useRoute();
27
28
  const router = useRouter();
28
29
  const { locale, t } = useI18n();
29
30
  const isCheating = useCheating();
31
+ const inheritedContext = useCELContext();
30
32
  const resolvedConfig = computedAsync(
31
33
  async () => MenuTabsConfigC.parse(await props.config.pipe(Effect.runPromise) ?? defaultConfig)
32
34
  );
@@ -43,9 +45,10 @@ function cleanPath(path) {
43
45
  return normalizedPath.length > 0 ? normalizedPath : "/";
44
46
  }
45
47
  function getEvaluationContext() {
48
+ const context = mergeDslContexts(props.context, inheritedContext);
46
49
  return {
47
- ...props.context ?? {},
48
- context: props.context ?? {}
50
+ ...context,
51
+ context
49
52
  };
50
53
  }
51
54
  const resolvedMenus = computed(
@@ -15,8 +15,9 @@ import { computedAsync } from "@vueuse/core";
15
15
  import { getProperty } from "dot-prop";
16
16
  import { Effect } from "effect";
17
17
  import { Pagination } from "reka-ui/namespaced";
18
- import { computed, ref, watch } from "vue";
18
+ import { computed, defineComponent, ref, watch } from "vue";
19
19
  import { useI18n } from "vue-i18n";
20
+ import { mergeDslContexts, provideCELContext, useCELContext } from "../../../plugins/cel/context";
20
21
  import { useTableRenderers } from "../../../composables/useTableRenderers";
21
22
  import { getLocalizedText } from "../../../utils/coders";
22
23
  import {
@@ -53,6 +54,7 @@ const { t, locale } = useI18n();
53
54
  const slots = defineSlots();
54
55
  const { $dsl } = useNuxtApp();
55
56
  const isCheating = useCheating();
57
+ const inheritedDslContext = useCELContext();
56
58
  const { resolveTableRenderer } = useTableRenderers();
57
59
  const containerRef = ref(null);
58
60
  const appliedInitialStateKey = ref("");
@@ -77,6 +79,12 @@ function getColumnTitle(column) {
77
79
  function getColumnTooltip(column) {
78
80
  return getLocalizedText(column.tooltip, locale.value);
79
81
  }
82
+ function getRowDslContext(row, index) {
83
+ return mergeDslContexts({
84
+ row,
85
+ index: BigInt(index)
86
+ }, inheritedDslContext);
87
+ }
80
88
  function translate(column) {
81
89
  if (Array.isArray(column.columns) && column.columns.length > 0) {
82
90
  return {
@@ -104,7 +112,11 @@ function translate(column) {
104
112
  if (slot) {
105
113
  return slot({ cell: ctx });
106
114
  }
107
- return renderer.cell({ ctx, options });
115
+ return renderer.cell({
116
+ ctx,
117
+ dslContext: getRowDslContext(ctx.row.original, ctx.row.index),
118
+ options
119
+ });
108
120
  },
109
121
  accessorFn: (row, index) => {
110
122
  const key = column.accessor;
@@ -112,10 +124,7 @@ function translate(column) {
112
124
  return getProperty(row, key);
113
125
  } else if (key !== void 0) {
114
126
  try {
115
- return $dsl.evaluate`${key.read}`({
116
- row,
117
- index: BigInt(index)
118
- });
127
+ return $dsl.evaluate`${key.read}`(getRowDslContext(row, index));
119
128
  } catch (e) {
120
129
  console.error(e);
121
130
  return void 0;
@@ -144,6 +153,25 @@ const paginationLeft = computed(() => currentConfig.value?.paginationLeft ?? "")
144
153
  const paginationRight = computed(() => currentConfig.value?.paginationRight ?? "");
145
154
  const resolvedPaginationPageSizes = computed(() => normalizePaginationPageSizes(currentConfig.value?.paginationPageSizes));
146
155
  const isConfiguratorOpen = ref(false);
156
+ const TableRowCELContext = defineComponent({
157
+ name: "TableRowCELContext",
158
+ props: {
159
+ row: {
160
+ default: void 0
161
+ },
162
+ index: {
163
+ type: Number,
164
+ required: true
165
+ }
166
+ },
167
+ setup(props2, { slots: slots2 }) {
168
+ provideCELContext({
169
+ row: props2.row,
170
+ index: BigInt(props2.index)
171
+ });
172
+ return () => slots2.default?.();
173
+ }
174
+ });
147
175
  function handleConfiguratorConfirm(nextConfig) {
148
176
  currentConfig.value = nextConfig;
149
177
  emit("update:config", nextConfig);
@@ -174,7 +202,7 @@ function getRowId(originalRow, index, parent) {
174
202
  const key = $dsl.evaluate`${expression}`(
175
203
  {
176
204
  row: originalRow,
177
- index,
205
+ index: BigInt(index),
178
206
  parent: parent ? {
179
207
  id: parent.id,
180
208
  index: BigInt(parent.index),
@@ -196,10 +224,7 @@ function getSubRows(row, index) {
196
224
  return void 0;
197
225
  }
198
226
  try {
199
- const value = $dsl.evaluate`${expression}`({
200
- row,
201
- index
202
- });
227
+ const value = $dsl.evaluate`${expression}`(getRowDslContext(row, index));
203
228
  return Array.isArray(value) ? value : void 0;
204
229
  } catch (e) {
205
230
  console.error(e);
@@ -212,11 +237,11 @@ function enableRowSelection(row) {
212
237
  return true;
213
238
  }
214
239
  try {
215
- return Boolean($dsl.evaluate`${expression}`({
240
+ return Boolean($dsl.evaluate`${expression}`(mergeDslContexts({
216
241
  row: row.original,
217
242
  index: BigInt(row.index),
218
243
  id: row.id
219
- }));
244
+ }, inheritedDslContext)));
220
245
  } catch (e) {
221
246
  console.error(e);
222
247
  return true;
@@ -228,11 +253,11 @@ function enableMultiRowSelection(row) {
228
253
  return true;
229
254
  }
230
255
  try {
231
- return Boolean($dsl.evaluate`${expression}`({
256
+ return Boolean($dsl.evaluate`${expression}`(mergeDslContexts({
232
257
  row: row.original,
233
258
  index: BigInt(row.index),
234
259
  id: row.id
235
- }));
260
+ }, inheritedDslContext)));
236
261
  } catch (e) {
237
262
  console.error(e);
238
263
  return true;
@@ -352,13 +377,13 @@ function getCellStyles(ctx) {
352
377
  if (!expression)
353
378
  return {};
354
379
  try {
355
- const result = $dsl.evaluate`${expression}`({
380
+ const result = $dsl.evaluate`${expression}`(mergeDslContexts({
356
381
  row: ctx.row.original,
357
382
  index: BigInt(ctx.row.index),
358
383
  id: ctx.column.id,
359
384
  selected: ctx.row.getIsSelected(),
360
385
  pinned: ctx.column.getIsPinned()
361
- });
386
+ }, inheritedDslContext));
362
387
  return isStyleRecord(result) ? result : {};
363
388
  } catch (e) {
364
389
  console.error(e);
@@ -737,10 +762,15 @@ export {
737
762
  ...getCellStyles(cell.getContext())
738
763
  }"
739
764
  >
740
- <FlexRender
741
- :render="cell.column.columnDef.cell"
742
- :props="cell.getContext()"
743
- />
765
+ <TableRowCELContext
766
+ :row="cell.row.original"
767
+ :index="cell.row.index"
768
+ >
769
+ <FlexRender
770
+ :render="cell.column.columnDef.cell"
771
+ :props="cell.getContext()"
772
+ />
773
+ </TableRowCELContext>
744
774
  </td>
745
775
  </tr>
746
776
  </tbody>
@@ -0,0 +1 @@
1
+ export { provideCELContext } from '../plugins/cel/context.js';
@@ -0,0 +1 @@
1
+ export { provideCELContext } from "../plugins/cel/context.js";
@@ -0,0 +1 @@
1
+ export { useCELContext } from '../plugins/cel/context.js';
@@ -0,0 +1 @@
1
+ export { useCELContext } from "../plugins/cel/context.js";
@@ -1,2 +1,6 @@
1
+ export declare function mergeDslContexts(...contexts: Array<Record<string, unknown> | undefined>): Record<string, unknown>;
1
2
  export declare function setGlobalDslContext(context: Record<string, unknown>): void;
2
3
  export declare function getGlobalDslContext(): Record<string, unknown>;
4
+ export declare function getProvidedDslContext(): Record<string, unknown>;
5
+ export declare function provideCELContext(context: Record<string, unknown>): void;
6
+ export declare function useCELContext(overrides?: Record<string, unknown>): Record<string, unknown>;
@@ -1,7 +1,27 @@
1
+ import defu from "defu";
2
+ import { hasInjectionContext, inject, provide } from "vue";
3
+ const dslContextKey = Symbol("shwfed-cel-context");
4
+ const emptyDslContext = {};
1
5
  let globalDslContext = {};
6
+ export function mergeDslContexts(...contexts) {
7
+ const definedContexts = contexts.filter((context) => context !== void 0);
8
+ return defu({}, ...definedContexts);
9
+ }
2
10
  export function setGlobalDslContext(context) {
3
11
  globalDslContext = context;
4
12
  }
5
13
  export function getGlobalDslContext() {
6
14
  return globalDslContext;
7
15
  }
16
+ export function getProvidedDslContext() {
17
+ if (!hasInjectionContext()) {
18
+ return emptyDslContext;
19
+ }
20
+ return inject(dslContextKey, emptyDslContext);
21
+ }
22
+ export function provideCELContext(context) {
23
+ provide(dslContextKey, mergeDslContexts(context, getProvidedDslContext()));
24
+ }
25
+ export function useCELContext(overrides) {
26
+ return mergeDslContexts(overrides, getProvidedDslContext());
27
+ }
@@ -1,7 +1,7 @@
1
1
  import { defineNuxtPlugin, useRuntimeConfig } from "#app";
2
2
  import defu from "defu";
3
3
  import { createEnvironment } from "./env.js";
4
- import { getGlobalDslContext } from "./context.js";
4
+ import { getGlobalDslContext, getProvidedDslContext } from "./context.js";
5
5
  import { useNavigatorLanguage } from "@vueuse/core";
6
6
  import { TZDate } from "@date-fns/tz";
7
7
  export default defineNuxtPlugin({
@@ -14,7 +14,7 @@ export default defineNuxtPlugin({
14
14
  build: config.ci.build !== void 0 ? BigInt(config.ci.build) : void 0
15
15
  });
16
16
  const evaluate = (...args) => (context) => {
17
- return env.evaluate(String.raw(...args), defu({}, getGlobalDslContext(), context, {
17
+ return env.evaluate(String.raw(...args), defu({}, context, getProvidedDslContext(), getGlobalDslContext(), {
18
18
  now: new TZDate(),
19
19
  today: new TZDate(),
20
20
  location: new URL(location.href),
@@ -387,7 +387,7 @@ defineTableRenderer(
387
387
  align: z.enum(["left", "center", "right"]).default("left")
388
388
  },
389
389
  {
390
- cell: ({ ctx, options }) => {
390
+ cell: ({ ctx, dslContext, options }) => {
391
391
  const rawValue = ctx.cell.getValue();
392
392
  const isEmpty = rawValue === void 0 || rawValue === null;
393
393
  const align = isEmpty ? "center" : options.align ?? "left";
@@ -397,10 +397,7 @@ defineTableRenderer(
397
397
  try {
398
398
  let text = String(ctx.cell.getValue());
399
399
  if (options.copyExpression) {
400
- text = String($dsl.evaluate`${options.copyExpression}`({
401
- row: ctx.row.original,
402
- index: BigInt(ctx.row.index)
403
- }));
400
+ text = String($dsl.evaluate`${options.copyExpression}`(dslContext));
404
401
  }
405
402
  await navigator.clipboard.writeText(text);
406
403
  } catch (e) {
@@ -5,6 +5,7 @@ export type TableRendererId = string;
5
5
  export type TableRendererColumnDefOverrides<TData extends RowData = unknown> = Partial<Pick<ColumnDef<TData, unknown>, 'enableResizing' | 'enableSorting' | 'enableMultiSort' | 'enablePinning' | 'sortingFn' | 'size' | 'meta'>>;
6
6
  export type TableRendererCellArgs<TData extends RowData, TValue, TOptions> = Readonly<{
7
7
  ctx: CellContext<TData, TValue>;
8
+ dslContext: Record<string, unknown>;
8
9
  options: TOptions;
9
10
  }>;
10
11
  export type TableRendererHeaderArgs<TData extends RowData, TValue, TOptions> = Readonly<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shwfed/nuxt",
3
- "version": "0.11.21",
3
+ "version": "0.11.23",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "type": "module",