@bpmn-io/form-js-playground 1.20.1 → 1.21.1

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.
@@ -585,7 +585,7 @@
585
585
  *
586
586
  * @return {Object} map with { attrValue => [ a, b, c ] }
587
587
  */
588
- function groupBy(collection, extractor, grouped = {}) {
588
+ function groupBy$1(collection, extractor, grouped = {}) {
589
589
  extractor = toExtractor(extractor);
590
590
  forEach(collection, function (val) {
591
591
  let discriminator = extractor(val) || '_';
@@ -600,7 +600,7 @@
600
600
  function uniqueBy(extractor, ...collections) {
601
601
  extractor = toExtractor(extractor);
602
602
  let grouped = {};
603
- forEach(collections, c => groupBy(c, extractor, grouped));
603
+ forEach(collections, c => groupBy$1(c, extractor, grouped));
604
604
  let result = map(grouped, function (val, key) {
605
605
  return val[0];
606
606
  });
@@ -53226,16 +53226,38 @@ Please report this to https://github.com/markedjs/marked.`, e) {
53226
53226
  * @returns {any}
53227
53227
  */
53228
53228
  evaluate(expression, data = {}) {
53229
- if (!expression) {
53229
+ if (!this.isExpression(expression)) {
53230
53230
  return null;
53231
53231
  }
53232
- if (!isString$2(expression) || !expression.startsWith('=')) {
53232
+ try {
53233
+ const {
53234
+ value: result
53235
+ } = evaluate$1(expression.slice(1), data);
53236
+ return result;
53237
+ } catch (error) {
53238
+ this._eventBus.fire('error', {
53239
+ error
53240
+ });
53241
+ return null;
53242
+ }
53243
+ }
53244
+
53245
+ /**
53246
+ * Evaluate a unary test expression. Returns null for invalid/missing expressions.
53247
+ *
53248
+ * @param {string} expression
53249
+ * @param {import('../../types').Data} [data]
53250
+ *
53251
+ * @returns {boolean|null}
53252
+ */
53253
+ evaluateUnaryTest(expression, data = {}) {
53254
+ if (!this.isExpression(expression)) {
53233
53255
  return null;
53234
53256
  }
53235
53257
  try {
53236
53258
  const {
53237
53259
  value: result
53238
- } = evaluate$1(expression.slice(1), data);
53260
+ } = unaryTest(expression.slice(1), data);
53239
53261
  return result;
53240
53262
  } catch (error) {
53241
53263
  this._eventBus.fire('error', {
@@ -53558,6 +53580,110 @@ Please report this to https://github.com/markedjs/marked.`, e) {
53558
53580
  });
53559
53581
  return result;
53560
53582
  }
53583
+
53584
+ /**
53585
+ * Returns the options data for the provided if they can be simply determined, ignoring expression defined options.
53586
+ *
53587
+ * @param {object} formField
53588
+ * @param {object} formData
53589
+ */
53590
+ function getSimpleOptionsData(formField, formData) {
53591
+ const {
53592
+ valuesExpression: optionsExpression,
53593
+ valuesKey: optionsKey,
53594
+ values: staticOptions
53595
+ } = formField;
53596
+ if (optionsExpression) {
53597
+ return null;
53598
+ }
53599
+ return optionsKey ? get$1(formData, [optionsKey]) : staticOptions;
53600
+ }
53601
+
53602
+ /**
53603
+ * Normalizes the provided options data to a format that can be used by the select components.
53604
+ * If the options data is not valid, it is filtered out.
53605
+ *
53606
+ * @param {any[]} optionsData
53607
+ *
53608
+ * @returns {object[]}
53609
+ */
53610
+ function normalizeOptionsData(optionsData) {
53611
+ return optionsData.filter(_isAllowedValue).map(_normalizeOption).filter(o => !isNil$1(o));
53612
+ }
53613
+
53614
+ /**
53615
+ * Creates an options object with default values if no options are provided.
53616
+ *
53617
+ * @param {object} options
53618
+ *
53619
+ * @returns {object}
53620
+ */
53621
+ function createEmptyOptions(options = {}) {
53622
+ const defaults = {};
53623
+
53624
+ // provide default options if valuesKey and valuesExpression are not set
53625
+ if (!options.valuesKey && !options.valuesExpression) {
53626
+ defaults.values = [{
53627
+ label: 'Value',
53628
+ value: 'value'
53629
+ }];
53630
+ }
53631
+ return {
53632
+ ...defaults,
53633
+ ...options
53634
+ };
53635
+ }
53636
+
53637
+ /**
53638
+ * Converts the provided option to a normalized format.
53639
+ * If the option is not valid, null is returned.
53640
+ *
53641
+ * @param {object} option
53642
+ * @param {string} option.label
53643
+ * @param {*} option.value
53644
+ *
53645
+ * @returns
53646
+ */
53647
+ function _normalizeOption(option) {
53648
+ // (1) simple primitive case, use it as both label and value
53649
+ if (_isAllowedPrimitive(option)) {
53650
+ return {
53651
+ value: option,
53652
+ label: `${option}`
53653
+ };
53654
+ }
53655
+ if (isObject(option)) {
53656
+ const isValidLabel = _isValidLabel(option.label);
53657
+
53658
+ // (2) no label provided, but value is a simple primitive, use it as label and value
53659
+ if (!isValidLabel && _isAllowedPrimitive(option.value)) {
53660
+ return {
53661
+ value: option.value,
53662
+ label: `${option.value}`
53663
+ };
53664
+ }
53665
+
53666
+ // (3) both label and value are provided, use them as is
53667
+ if (isValidLabel && _isAllowedValue(option.value)) {
53668
+ return option;
53669
+ }
53670
+ }
53671
+ return null;
53672
+ }
53673
+ function _isAllowedPrimitive(value) {
53674
+ const isAllowedPrimitiveType = ['number', 'string', 'boolean'].includes(typeof value);
53675
+ const isValid = value || value === 0 || value === false;
53676
+ return isAllowedPrimitiveType && isValid;
53677
+ }
53678
+ function _isValidLabel(label) {
53679
+ return label && isString$2(label);
53680
+ }
53681
+ function _isAllowedValue(value) {
53682
+ if (isObject(value)) {
53683
+ return Object.keys(value).length > 0;
53684
+ }
53685
+ return _isAllowedPrimitive(value);
53686
+ }
53561
53687
  const FormRenderContext = G$1({
53562
53688
  Empty: props => {
53563
53689
  return null;
@@ -53598,7 +53724,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
53598
53724
  },
53599
53725
  hoverInfo: {
53600
53726
  cleanup: () => {}
53601
- }
53727
+ },
53728
+ applyVisibilityConditions: true
53602
53729
  });
53603
53730
  const LocalExpressionContext = G$1({
53604
53731
  data: null,
@@ -53678,135 +53805,29 @@ Please report this to https://github.com/markedjs/marked.`, e) {
53678
53805
  /**
53679
53806
  * If the value is a valid expression, it is evaluated and returned. Otherwise, it is returned as-is.
53680
53807
  *
53681
- * @param {any} expressionLanguage - The expression language to use.
53808
+ * @param {import('../types').ExpressionLanguage} expressionLanguage - The expression language to use.
53682
53809
  * @param {any} value - The static value or expression to evaluate.
53683
53810
  * @param {Object} expressionContextInfo - The context information to use.
53684
53811
  * @returns {any} - Evaluated value or the original value if not an expression.
53685
53812
  */
53686
53813
  function runExpressionEvaluation(expressionLanguage, value, expressionContextInfo) {
53687
- if (expressionLanguage && expressionLanguage.isExpression(value)) {
53814
+ if (expressionLanguage.isExpression(value)) {
53688
53815
  return expressionLanguage.evaluate(value, buildExpressionContext(expressionContextInfo));
53689
53816
  }
53690
53817
  return value;
53691
53818
  }
53692
53819
 
53693
53820
  /**
53694
- * Evaluate if condition is met reactively based on the conditionChecker and form data.
53821
+ * Evaluate a value as a unary test expression. Returns null for invalid/missing expressions or
53822
+ * if the expression language is not available.
53695
53823
  *
53696
- * @param {string | undefined} condition
53697
- *
53698
- * @returns {boolean} true if condition is met or no condition or condition checker exists
53699
- */
53700
- function useCondition(condition) {
53701
- const conditionChecker = useService$2('conditionChecker', false);
53702
- const expressionContextInfo = q$2(LocalExpressionContext);
53703
- return F$2(() => {
53704
- return conditionChecker ? conditionChecker.check(condition, buildExpressionContext(expressionContextInfo)) : null;
53705
- }, [conditionChecker, condition, expressionContextInfo]);
53706
- }
53707
-
53708
- /**
53709
- * Returns the options data for the provided if they can be simply determined, ignoring expression defined options.
53710
- *
53711
- * @param {object} formField
53712
- * @param {object} formData
53713
- */
53714
- function getSimpleOptionsData(formField, formData) {
53715
- const {
53716
- valuesExpression: optionsExpression,
53717
- valuesKey: optionsKey,
53718
- values: staticOptions
53719
- } = formField;
53720
- if (optionsExpression) {
53721
- return null;
53722
- }
53723
- return optionsKey ? get$1(formData, [optionsKey]) : staticOptions;
53724
- }
53725
-
53726
- /**
53727
- * Normalizes the provided options data to a format that can be used by the select components.
53728
- * If the options data is not valid, it is filtered out.
53729
- *
53730
- * @param {any[]} optionsData
53731
- *
53732
- * @returns {object[]}
53824
+ * @param {import('../types').ExpressionLanguage} expressionLanguage - The expression language to use.
53825
+ * @param {string} value - The unary test expression to evaluate.
53826
+ * @param {Object} expressionContextInfo - The context information to use.
53827
+ * @returns {boolean | null} - Evaluated result, or null if expression is invalid/missing.
53733
53828
  */
53734
- function normalizeOptionsData(optionsData) {
53735
- return optionsData.filter(_isAllowedValue).map(_normalizeOption).filter(o => !isNil$1(o));
53736
- }
53737
-
53738
- /**
53739
- * Creates an options object with default values if no options are provided.
53740
- *
53741
- * @param {object} options
53742
- *
53743
- * @returns {object}
53744
- */
53745
- function createEmptyOptions(options = {}) {
53746
- const defaults = {};
53747
-
53748
- // provide default options if valuesKey and valuesExpression are not set
53749
- if (!options.valuesKey && !options.valuesExpression) {
53750
- defaults.values = [{
53751
- label: 'Value',
53752
- value: 'value'
53753
- }];
53754
- }
53755
- return {
53756
- ...defaults,
53757
- ...options
53758
- };
53759
- }
53760
-
53761
- /**
53762
- * Converts the provided option to a normalized format.
53763
- * If the option is not valid, null is returned.
53764
- *
53765
- * @param {object} option
53766
- * @param {string} option.label
53767
- * @param {*} option.value
53768
- *
53769
- * @returns
53770
- */
53771
- function _normalizeOption(option) {
53772
- // (1) simple primitive case, use it as both label and value
53773
- if (_isAllowedPrimitive(option)) {
53774
- return {
53775
- value: option,
53776
- label: `${option}`
53777
- };
53778
- }
53779
- if (isObject(option)) {
53780
- const isValidLabel = _isValidLabel(option.label);
53781
-
53782
- // (2) no label provided, but value is a simple primitive, use it as label and value
53783
- if (!isValidLabel && _isAllowedPrimitive(option.value)) {
53784
- return {
53785
- value: option.value,
53786
- label: `${option.value}`
53787
- };
53788
- }
53789
-
53790
- // (3) both label and value are provided, use them as is
53791
- if (isValidLabel && _isAllowedValue(option.value)) {
53792
- return option;
53793
- }
53794
- }
53795
- return null;
53796
- }
53797
- function _isAllowedPrimitive(value) {
53798
- const isAllowedPrimitiveType = ['number', 'string', 'boolean'].includes(typeof value);
53799
- const isValid = value || value === 0 || value === false;
53800
- return isAllowedPrimitiveType && isValid;
53801
- }
53802
- function _isValidLabel(label) {
53803
- return label && isString$2(label);
53804
- }
53805
- function _isAllowedValue(value) {
53806
- if (isObject(value)) {
53807
- return Object.keys(value).length > 0;
53808
- }
53809
- return _isAllowedPrimitive(value);
53829
+ function runUnaryTestEvaluation(expressionLanguage, value, expressionContextInfo) {
53830
+ return expressionLanguage.evaluateUnaryTest(value, buildExpressionContext(expressionContextInfo));
53810
53831
  }
53811
53832
 
53812
53833
  /**
@@ -54139,6 +54160,19 @@ Please report this to https://github.com/markedjs/marked.`, e) {
54139
54160
  }, [expressionLanguage, expressionContextInfo, value]);
54140
54161
  }
54141
54162
 
54163
+ /**
54164
+ * Evaluate a unary test expression reactively. Returns null for invalid/missing expressions.
54165
+ * The function is memoized to minimize re-renders.
54166
+ *
54167
+ * @param {string | undefined} value - A unary test expression to evaluate.
54168
+ * @returns {boolean | null} - Evaluated result, or null if expression is invalid/missing.
54169
+ */
54170
+ function useUnaryTestEvaluation(value) {
54171
+ const expressionLanguage = useService$2('expressionLanguage');
54172
+ const expressionContextInfo = q$2(LocalExpressionContext);
54173
+ return F$2(() => runUnaryTestEvaluation(expressionLanguage, value, expressionContextInfo), [expressionLanguage, expressionContextInfo, value]);
54174
+ }
54175
+
54142
54176
  /**
54143
54177
  * Returns the conditionally filtered data of a form reactively.
54144
54178
  * Memoised to minimize re-renders
@@ -54188,16 +54222,16 @@ Please report this to https://github.com/markedjs/marked.`, e) {
54188
54222
  */
54189
54223
  function useReadonly(formField, properties = {}) {
54190
54224
  const expressionLanguage = useService$2('expressionLanguage');
54191
- const conditionChecker = useService$2('conditionChecker', false);
54192
- const expressionContextInfo = q$2(LocalExpressionContext);
54193
54225
  const {
54194
54226
  readonly
54195
54227
  } = formField;
54228
+ const isExpression = expressionLanguage && expressionLanguage.isExpression(readonly);
54229
+ const evaluatedReadonly = useUnaryTestEvaluation(isExpression ? readonly : undefined);
54196
54230
  if (properties.readOnly) {
54197
54231
  return true;
54198
54232
  }
54199
- if (expressionLanguage && expressionLanguage.isExpression(readonly)) {
54200
- return conditionChecker ? conditionChecker.check(readonly, buildExpressionContext(expressionContextInfo)) : false;
54233
+ if (isExpression) {
54234
+ return evaluatedReadonly === true;
54201
54235
  }
54202
54236
  return readonly || false;
54203
54237
  }
@@ -54937,7 +54971,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
54937
54971
  const {
54938
54972
  Element,
54939
54973
  Hidden,
54940
- Column
54974
+ Column,
54975
+ applyVisibilityConditions
54941
54976
  } = q$2(FormRenderContext);
54942
54977
  const {
54943
54978
  formId
@@ -54961,7 +54996,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
54961
54996
 
54962
54997
  // add precedence: global readonly > form field disabled
54963
54998
  const disabled = !properties.readOnly && (properties.disabled || field.disabled || false);
54964
- const hidden = useCondition(field.conditional && field.conditional.hide || null);
54999
+ const conditionResult = useUnaryTestEvaluation(field.conditional && field.conditional.hide || null);
55000
+ const hidden = applyVisibilityConditions ? conditionResult : null;
54965
55001
  const instanceId = F$2(() => {
54966
55002
  if (!formFieldInstanceRegistry) {
54967
55003
  return null;
@@ -59049,7 +59085,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59049
59085
 
59050
59086
  /**
59051
59087
  * @typedef DocumentEndpointBuilder
59052
- * @property {(document: DocumentMetadata) => string} buildUrl
59088
+ * @property {(document: DocumentMetadata) => string} [buildUrl]
59089
+ * @property {(document: DocumentMetadata) => RequestInit|undefined} [buildRequestInit]
59053
59090
  */
59054
59091
 
59055
59092
  /**
@@ -59100,13 +59137,18 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59100
59137
  class: `fjs-${type$k}-document-container`,
59101
59138
  id: domId,
59102
59139
  children: data.map((document, index) => {
59103
- const finalEndpoint = tryCatch(() => documentEndpointBuilder?.buildUrl(document)) ?? document.endpoint;
59104
- return isValidDocumentEndpoint(finalEndpoint) ? o(DocumentRenderer, {
59140
+ const finalEndpoint = tryCatch(() => documentEndpointBuilder?.buildUrl?.(document)) ?? document.endpoint;
59141
+ if (!isValidDocumentEndpoint(finalEndpoint)) {
59142
+ return null;
59143
+ }
59144
+ const requestInit = getDocumentRequestInit(documentEndpointBuilder, document);
59145
+ return o(DocumentRenderer, {
59105
59146
  documentMetadata: document,
59106
59147
  endpoint: finalEndpoint,
59148
+ requestInit: requestInit,
59107
59149
  maxHeight: maxHeight,
59108
59150
  domId: `${domId}-${index}`
59109
- }, document.documentId) : null;
59151
+ }, document.documentId);
59110
59152
  })
59111
59153
  }), o(Errors, {
59112
59154
  id: errorMessageId,
@@ -59182,13 +59224,15 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59182
59224
  * @param {string} props.fileName
59183
59225
  * @param {Function} props.onError
59184
59226
  * @param {string} props.errorMessageId
59227
+ * @param {RequestInit|undefined} props.requestInit
59185
59228
  * @returns {import("preact").JSX.Element}
59186
59229
  */
59187
59230
  function PdfRenderer(props) {
59188
59231
  const {
59189
59232
  url,
59190
59233
  onError,
59191
- errorMessageId
59234
+ errorMessageId,
59235
+ requestInit
59192
59236
  } = props;
59193
59237
  /** @type {ReturnType<typeof import("preact/hooks").useState<null | string>>} */
59194
59238
  const [pdfObjectUrl, setPdfObjectUrl] = h(null);
@@ -59198,7 +59242,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59198
59242
  let objectUrl = null;
59199
59243
  const fetchPdf = async () => {
59200
59244
  try {
59201
- const response = await fetch(url);
59245
+ const response = await fetch(url, requestInit);
59202
59246
  if (!response.ok) {
59203
59247
  setHasError(true);
59204
59248
  onError();
@@ -59218,7 +59262,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59218
59262
  URL.revokeObjectURL(objectUrl);
59219
59263
  }
59220
59264
  };
59221
- }, [url, onError]);
59265
+ }, [url, onError, requestInit]);
59222
59266
  return o(k$3, {
59223
59267
  children: [pdfObjectUrl !== null ? o("embed", {
59224
59268
  src: pdfObjectUrl,
@@ -59231,12 +59275,61 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59231
59275
  });
59232
59276
  }
59233
59277
 
59278
+ /**
59279
+ * @param {Object} props
59280
+ * @param {string} props.url
59281
+ * @param {string} props.alt
59282
+ * @param {Function} props.onError
59283
+ * @param {RequestInit|undefined} props.requestInit
59284
+ * @returns {import("preact").JSX.Element}
59285
+ */
59286
+ function ImageRenderer(props) {
59287
+ const {
59288
+ url,
59289
+ alt,
59290
+ onError,
59291
+ requestInit
59292
+ } = props;
59293
+ /** @type {ReturnType<typeof import("preact/hooks").useState<null | string>>} */
59294
+ const [imageObjectUrl, setImageObjectUrl] = h(null);
59295
+ p(() => {
59296
+ /** @type {null | string} */
59297
+ let objectUrl = null;
59298
+ const fetchImage = async () => {
59299
+ try {
59300
+ const response = await fetch(url, requestInit);
59301
+ if (!response.ok) {
59302
+ onError();
59303
+ return;
59304
+ }
59305
+ const blob = await response.blob();
59306
+ objectUrl = URL.createObjectURL(blob);
59307
+ setImageObjectUrl(objectUrl);
59308
+ } catch {
59309
+ onError();
59310
+ }
59311
+ };
59312
+ fetchImage();
59313
+ return () => {
59314
+ if (objectUrl) {
59315
+ URL.revokeObjectURL(objectUrl);
59316
+ }
59317
+ };
59318
+ }, [url, onError, requestInit]);
59319
+ return imageObjectUrl !== null ? o("img", {
59320
+ src: imageObjectUrl,
59321
+ alt: alt,
59322
+ class: `fjs-${type$k}-image`
59323
+ }) : null;
59324
+ }
59325
+
59234
59326
  /**
59235
59327
  *
59236
59328
  * @param {Object} props
59237
59329
  * @param {DocumentMetadata} props.documentMetadata
59238
59330
  * @param {string} props.endpoint
59239
59331
  * @param {string} props.domId
59332
+ * @param {RequestInit|undefined} props.requestInit
59240
59333
  * @param {number|undefined} props.maxHeight
59241
59334
  *
59242
59335
  * @returns {import("preact").JSX.Element}
@@ -59246,7 +59339,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59246
59339
  documentMetadata,
59247
59340
  endpoint,
59248
59341
  maxHeight,
59249
- domId
59342
+ domId,
59343
+ requestInit
59250
59344
  } = props;
59251
59345
  const {
59252
59346
  metadata
@@ -59265,13 +59359,15 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59265
59359
  maxHeight
59266
59360
  },
59267
59361
  "aria-describedby": hasError ? errorMessageId : undefined,
59268
- children: [o("img", {
59269
- src: endpoint,
59362
+ children: [o(ImageRenderer, {
59363
+ url: endpoint,
59270
59364
  alt: metadata.fileName,
59271
- class: `fjs-${type$k}-image`
59365
+ requestInit: requestInit,
59366
+ onError: () => setHasError(true)
59272
59367
  }), o(DownloadButton, {
59273
59368
  endpoint: endpoint,
59274
59369
  fileName: metadata.fileName,
59370
+ requestInit: requestInit,
59275
59371
  onDownloadError: () => {
59276
59372
  setHasError(true);
59277
59373
  }
@@ -59291,6 +59387,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59291
59387
  children: o(PdfRenderer, {
59292
59388
  url: endpoint,
59293
59389
  fileName: metadata.fileName,
59390
+ requestInit: requestInit,
59294
59391
  onError: () => setHasError(true),
59295
59392
  errorMessageId: errorMessageId
59296
59393
  })
@@ -59311,6 +59408,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59311
59408
  }), o(DownloadButton, {
59312
59409
  endpoint: endpoint,
59313
59410
  fileName: metadata.fileName,
59411
+ requestInit: requestInit,
59314
59412
  onDownloadError: () => {
59315
59413
  setHasError(true);
59316
59414
  }
@@ -59323,6 +59421,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59323
59421
  * @param {string} props.endpoint
59324
59422
  * @param {string} props.fileName
59325
59423
  * @param {Function} props.onDownloadError
59424
+ * @param {RequestInit|undefined} props.requestInit
59326
59425
  *
59327
59426
  * @returns {import("preact").JSX.Element}
59328
59427
  */
@@ -59330,11 +59429,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59330
59429
  const {
59331
59430
  endpoint,
59332
59431
  fileName,
59333
- onDownloadError
59432
+ onDownloadError,
59433
+ requestInit
59334
59434
  } = props;
59335
59435
  const handleDownload = async () => {
59336
59436
  try {
59337
- const response = await fetch(endpoint);
59437
+ const response = await fetch(endpoint, requestInit);
59338
59438
  if (!response.ok) {
59339
59439
  onDownloadError();
59340
59440
  return;
@@ -59388,6 +59488,16 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59388
59488
  return isInViewport;
59389
59489
  }
59390
59490
 
59491
+ /**
59492
+ * @param {DocumentEndpointBuilder | null} documentEndpointBuilder
59493
+ * @param {DocumentMetadata} document
59494
+ * @returns {RequestInit|undefined}
59495
+ */
59496
+ function getDocumentRequestInit(documentEndpointBuilder, document) {
59497
+ const requestInit = tryCatch(() => documentEndpointBuilder?.buildRequestInit?.(document));
59498
+ return requestInit !== null && typeof requestInit === 'object' ? requestInit : undefined;
59499
+ }
59500
+
59391
59501
  /**
59392
59502
  * @template T
59393
59503
  * @param {() => T} fn - Function to execute
@@ -59560,6 +59670,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59560
59670
 
59561
59671
  /**
59562
59672
  * @typedef { import('../types').Schema } Schema
59673
+ * @typedef { import('../types').ExpressionLanguage } ExpressionLanguage
59674
+ * @typedef { import('../types').Templating } Templating
59563
59675
  */
59564
59676
 
59565
59677
  /**
@@ -59582,8 +59694,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59582
59694
  *
59583
59695
  * @param {Schema} schema
59584
59696
  * @param {object} [options]
59585
- * @param {any} [options.expressionLanguage]
59586
- * @param {any} [options.templating]
59697
+ * @param {ExpressionLanguage} [options.expressionLanguage]
59698
+ * @param {Templating} [options.templating]
59587
59699
  * @param {any} [options.formFields]
59588
59700
  * @param {boolean} [options.inputs=true]
59589
59701
  * @param {boolean} [options.outputs=true]
@@ -59682,15 +59794,26 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59682
59794
  return ids;
59683
59795
  };
59684
59796
 
59797
+ /**
59798
+ * @typedef { import('../../types').ExpressionLanguage } ExpressionLanguage
59799
+ */
59800
+
59685
59801
  /**
59686
59802
  * @typedef {object} Condition
59687
59803
  * @property {string} [hide]
59688
59804
  */
59689
59805
 
59690
59806
  class ConditionChecker {
59691
- constructor(formFieldRegistry, pathRegistry, eventBus) {
59807
+ /**
59808
+ * @param {Object} formFieldRegistry
59809
+ * @param {Object} pathRegistry
59810
+ * @param {ExpressionLanguage} expressionLanguage
59811
+ * @param {Object} eventBus
59812
+ */
59813
+ constructor(formFieldRegistry, pathRegistry, expressionLanguage, eventBus) {
59692
59814
  this._formFieldRegistry = formFieldRegistry;
59693
59815
  this._pathRegistry = pathRegistry;
59816
+ this._expressionLanguage = expressionLanguage;
59694
59817
  this._eventBus = eventBus;
59695
59818
  }
59696
59819
 
@@ -59813,24 +59936,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59813
59936
  * @returns {boolean|null}
59814
59937
  */
59815
59938
  check(condition, data = {}) {
59816
- if (!condition) {
59817
- return null;
59818
- }
59819
- if (!isString$2(condition) || !condition.startsWith('=')) {
59820
- return null;
59821
- }
59822
- try {
59823
- // cut off initial '='
59824
- const {
59825
- value: result
59826
- } = unaryTest(condition.slice(1), data);
59827
- return result;
59828
- } catch (error) {
59829
- this._eventBus.fire('error', {
59830
- error
59831
- });
59832
- return null;
59833
- }
59939
+ return this._expressionLanguage.evaluateUnaryTest(condition, data);
59834
59940
  }
59835
59941
 
59836
59942
  /**
@@ -59864,7 +59970,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
59864
59970
  return Array.isArray(parentObject) && (!parentObject.length || parentObject.every(item => item === undefined));
59865
59971
  }
59866
59972
  }
59867
- ConditionChecker.$inject = ['formFieldRegistry', 'pathRegistry', 'eventBus'];
59973
+ ConditionChecker.$inject = ['formFieldRegistry', 'pathRegistry', 'expressionLanguage', 'eventBus'];
59868
59974
  const ExpressionLanguageModule = {
59869
59975
  __init__: ['expressionLanguage', 'templating', 'conditionChecker'],
59870
59976
  expressionLanguage: ['type', FeelExpressionLanguage],
@@ -61391,6 +61497,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
61391
61497
  function invokeFunction$1(fn, args) {
61392
61498
  return fn.apply(null, args);
61393
61499
  }
61500
+
61501
+ /**
61502
+ * @typedef { import('../types').ExpressionLanguage } ExpressionLanguage
61503
+ */
61504
+
61394
61505
  const EMAIL_PATTERN = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
61395
61506
  const PHONE_PATTERN = /(\+|00)(297|93|244|1264|358|355|376|971|54|374|1684|1268|61|43|994|257|32|229|226|880|359|973|1242|387|590|375|501|1441|591|55|1246|673|975|267|236|1|61|41|56|86|225|237|243|242|682|57|269|238|506|53|5999|61|1345|357|420|49|253|1767|45|1809|1829|1849|213|593|20|291|212|34|372|251|358|679|500|33|298|691|241|44|995|44|233|350|224|590|220|245|240|30|1473|299|502|594|1671|592|852|504|385|509|36|62|44|91|246|353|98|964|354|972|39|1876|44|962|81|76|77|254|996|855|686|1869|82|383|965|856|961|231|218|1758|423|94|266|370|352|371|853|590|212|377|373|261|960|52|692|389|223|356|95|382|976|1670|258|222|1664|596|230|265|60|262|264|687|227|672|234|505|683|31|47|977|674|64|968|92|507|64|51|63|680|675|48|1787|1939|850|351|595|970|689|974|262|40|7|250|966|249|221|65|500|4779|677|232|503|378|252|508|381|211|239|597|421|386|46|268|1721|248|963|1649|235|228|66|992|690|993|670|676|1868|216|90|688|886|255|256|380|598|1|998|3906698|379|1784|58|1284|1340|84|678|681|685|967|27|260|263)(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{4,20}$/;
61396
61507
  const VALIDATE_FEEL_PROPERTIES = ['min', 'max', 'minLength', 'maxLength'];
@@ -61519,6 +61630,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
61519
61630
  }
61520
61631
  return errors;
61521
61632
  }
61633
+
61634
+ /**
61635
+ * @param {Object} validate
61636
+ * @param {ExpressionLanguage} expressionLanguage
61637
+ * @param {Object} expressionContextInfo
61638
+ */
61522
61639
  function evaluateFEELValues(validate, expressionLanguage, expressionContextInfo) {
61523
61640
  const evaluatedValidate = {
61524
61641
  ...validate
@@ -61531,6 +61648,13 @@ Please report this to https://github.com/markedjs/marked.`, e) {
61531
61648
  });
61532
61649
  return evaluatedValidate;
61533
61650
  }
61651
+
61652
+ /**
61653
+ * @param {Object} validate
61654
+ * @param {ExpressionLanguage} expressionLanguage
61655
+ * @param {Object} conditionChecker
61656
+ * @param {Object} form
61657
+ */
61534
61658
  function oldEvaluateFEELValues(validate, expressionLanguage, conditionChecker, form) {
61535
61659
  const evaluatedValidate = {
61536
61660
  ...validate
@@ -62159,7 +62283,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
62159
62283
  // helpers //////
62160
62284
 
62161
62285
  function groupByRow(components, ids) {
62162
- return groupBy(components, c => {
62286
+ return groupBy$1(components, c => {
62163
62287
  // mitigate missing row by creating new (handle legacy)
62164
62288
  const {
62165
62289
  layout
@@ -69664,7 +69788,26 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69664
69788
  const fillsAndSeparators = F$2(() => {
69665
69789
  return buildFills(groups, fillRoot, separatorFn);
69666
69790
  }, [groups, fillRoot, separatorFn]);
69667
- return fillsAndSeparators;
69791
+
69792
+ // Framework-agnostic fills from SlotFillManager
69793
+ const editorContext = q$2(FormEditorContext);
69794
+ const slotFillManager = editorContext ? editorContext.getService('slotFillManager', false) : null;
69795
+ const eventBus = editorContext ? editorContext.getService('eventBus', false) : null;
69796
+ const [managerFills, setManagerFills] = h([]);
69797
+ p(() => {
69798
+ if (!eventBus || !slotFillManager) {
69799
+ return;
69800
+ }
69801
+ setManagerFills(slotFillManager.getFills(name));
69802
+ const onChange = () => setManagerFills(slotFillManager.getFills(name));
69803
+ eventBus.on('slotFillManager.changed', onChange);
69804
+ return () => eventBus.off('slotFillManager.changed', onChange);
69805
+ }, [eventBus, slotFillManager, name]);
69806
+ return o(k$3, {
69807
+ children: [fillsAndSeparators, managerFills.map(fill => o(FillContainer, {
69808
+ fill: fill
69809
+ }, fill.fillId))]
69810
+ });
69668
69811
  };
69669
69812
 
69670
69813
  /**
@@ -69677,6 +69820,34 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69677
69820
  children: fill.children
69678
69821
  }, fill.id);
69679
69822
 
69823
+ /**
69824
+ * Mounts a single SlotFillManager fill's render callback into a DOM container.
69825
+ */
69826
+ function FillContainer({
69827
+ fill
69828
+ }) {
69829
+ const containerRef = _$2(null);
69830
+ const cleanupRef = _$2(null);
69831
+ p(() => {
69832
+ const container = containerRef.current;
69833
+ if (!container) {
69834
+ return;
69835
+ }
69836
+ cleanupRef.current = fill.render(container) || null;
69837
+ return () => {
69838
+ if (typeof cleanupRef.current === 'function') {
69839
+ cleanupRef.current();
69840
+ cleanupRef.current = null;
69841
+ }
69842
+ container.innerHTML = '';
69843
+ };
69844
+ }, [fill]);
69845
+ return o("div", {
69846
+ ref: containerRef,
69847
+ "data-slot-fill": fill.fillId
69848
+ });
69849
+ }
69850
+
69680
69851
  /**
69681
69852
  * Creates an array of fills, with separators inserted between groups.
69682
69853
  *
@@ -70546,6 +70717,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
70546
70717
  children: "Drag and drop components here to start designing."
70547
70718
  }), o("span", {
70548
70719
  children: "Use the preview window to test your form."
70720
+ }), o(Slot, {
70721
+ name: "editor-empty-state__footer"
70549
70722
  })]
70550
70723
  })
70551
70724
  });
@@ -70851,7 +71024,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
70851
71024
  Element: Element$1,
70852
71025
  Empty,
70853
71026
  Row,
70854
- hoverInfo: {}
71027
+ hoverInfo: {},
71028
+ applyVisibilityConditions: false
70855
71029
  }), []);
70856
71030
  const formContext = F$2(() => ({
70857
71031
  getService(type, strict = true) {
@@ -82446,9 +82620,162 @@ Please report this to https://github.com/markedjs/marked.`, e) {
82446
82620
  }
82447
82621
  }
82448
82622
  RenderInjector.$inject = ['eventBus'];
82623
+
82624
+ /**
82625
+ * Framework-agnostic service for managing slot fills.
82626
+ *
82627
+ * Fills are registered as render callbacks: `(container: HTMLElement) => (() => void) | void`.
82628
+ * The optional return value is a cleanup function called when the fill is removed or the slot unmounts.
82629
+ *
82630
+ * @example
82631
+ *
82632
+ * // Via config (simplest):
82633
+ * new FormEditor({
82634
+ * slots: {
82635
+ * 'editor-empty-state__footer': (container) => {
82636
+ * container.textContent = 'Hello from vanilla JS';
82637
+ * }
82638
+ * }
82639
+ * });
82640
+ *
82641
+ * // Via config (multiple fills per slot):
82642
+ * new FormEditor({
82643
+ * slots: {
82644
+ * 'editor-empty-state__footer': [
82645
+ * (container) => { container.textContent = 'First'; },
82646
+ * { render: (container) => { container.textContent = 'Second'; }, priority: 10 }
82647
+ * ]
82648
+ * }
82649
+ * });
82650
+ *
82651
+ * // Via service (runtime):
82652
+ * const slotFillManager = editor.get('slotFillManager');
82653
+ * slotFillManager.addFill('editor-empty-state__footer', 'my-fill', {
82654
+ * render: (container) => { ... },
82655
+ * priority: 10,
82656
+ * group: 'custom'
82657
+ * });
82658
+ */
82659
+ class SlotFillManager {
82660
+ /**
82661
+ * @param {Object} slotsConfig
82662
+ * @param {import('../../core/EventBus').EventBus} eventBus
82663
+ */
82664
+ constructor(slotsConfig, eventBus) {
82665
+ this._eventBus = eventBus;
82666
+
82667
+ /** @type {Array<{ slotName: string, fillId: string, render: Function, priority: number, group: string }>} */
82668
+ this._fills = [];
82669
+ this._populateFromConfig(slotsConfig);
82670
+ }
82671
+
82672
+ /**
82673
+ * Register a fill for a named slot.
82674
+ *
82675
+ * @param {string} slotName - The slot to fill.
82676
+ * @param {string} fillId - Unique identifier for this fill.
82677
+ * @param {Function|Object} options - A render callback `(container) => cleanup`, or `{ render, priority?, group? }`.
82678
+ */
82679
+ addFill(slotName, fillId, options) {
82680
+ const fill = normalizeFill(slotName, fillId, options);
82681
+ this._fills = [...this._fills.filter(f => f.fillId !== fillId), fill];
82682
+ this._eventBus.fire('slotFillManager.changed');
82683
+ }
82684
+
82685
+ /**
82686
+ * Remove a fill by its ID.
82687
+ *
82688
+ * @param {string} fillId
82689
+ */
82690
+ removeFill(fillId) {
82691
+ const remaining = this._fills.filter(f => f.fillId !== fillId);
82692
+ if (remaining.length === this._fills.length) {
82693
+ return;
82694
+ }
82695
+ this._fills = remaining;
82696
+ this._eventBus.fire('slotFillManager.changed');
82697
+ }
82698
+
82699
+ /**
82700
+ * Get fills for a given slot, sorted by group (alphabetical) then priority (descending).
82701
+ *
82702
+ * @param {string} slotName
82703
+ * @returns {Array<{ slotName: string, fillId: string, render: Function, priority: number, group: string }>}
82704
+ */
82705
+ getFills(slotName) {
82706
+ const matching = this._fills.filter(f => f.slotName === slotName);
82707
+ return sortFills(matching);
82708
+ }
82709
+
82710
+ /**
82711
+ * @private
82712
+ */
82713
+ _populateFromConfig(slotsConfig) {
82714
+ Object.entries(slotsConfig || {}).forEach(([slotName, value]) => {
82715
+ if (Array.isArray(value)) {
82716
+ value.forEach((entry, index) => {
82717
+ this.addFill(slotName, `config__${slotName}_${index}`, entry);
82718
+ });
82719
+ } else {
82720
+ this.addFill(slotName, `config__${slotName}`, value);
82721
+ }
82722
+ });
82723
+ }
82724
+ }
82725
+ SlotFillManager.$inject = ['config.slots', 'eventBus'];
82726
+
82727
+ // helpers //////////
82728
+
82729
+ /**
82730
+ * @param {string} slotName
82731
+ * @param {string} fillId
82732
+ * @param {Function|Object} options
82733
+ * @returns {{ slotName: string, fillId: string, render: Function, priority: number, group: string }}
82734
+ */
82735
+ function normalizeFill(slotName, fillId, options) {
82736
+ if (typeof options === 'function') {
82737
+ return {
82738
+ slotName,
82739
+ fillId,
82740
+ render: options,
82741
+ priority: 0,
82742
+ group: 'z_default'
82743
+ };
82744
+ }
82745
+ const {
82746
+ render,
82747
+ priority = 0,
82748
+ group = 'z_default'
82749
+ } = options;
82750
+ return {
82751
+ slotName,
82752
+ fillId,
82753
+ render,
82754
+ priority,
82755
+ group
82756
+ };
82757
+ }
82758
+
82759
+ /**
82760
+ * Sort fills by group (alphabetical) then by priority (descending) within each group.
82761
+ */
82762
+ function sortFills(fills) {
82763
+ const grouped = groupBy(fills, f => f.group);
82764
+ return Object.keys(grouped).sort().flatMap(key => grouped[key].toSorted((a, b) => b.priority - a.priority));
82765
+ }
82766
+ function groupBy(items, keyFn) {
82767
+ return items.reduce((groups, item) => {
82768
+ const key = keyFn(item);
82769
+ return {
82770
+ ...groups,
82771
+ [key]: [...(groups[key] || []), item]
82772
+ };
82773
+ }, {});
82774
+ }
82449
82775
  const RenderInjectionModule = {
82450
- __init__: ['renderInjector'],
82451
- renderInjector: ['type', RenderInjector]
82776
+ __init__: ['renderInjector', 'slotFillManager'],
82777
+ renderInjector: ['type', RenderInjector],
82778
+ slotFillManager: ['type', SlotFillManager]
82452
82779
  };
82453
82780
  var _path;
82454
82781
  function _extends() {
@@ -84627,6 +84954,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
84627
84954
  editorProperties,
84628
84955
  viewerAdditionalModules,
84629
84956
  editorAdditionalModules,
84957
+ editorSlots,
84630
84958
  propertiesPanel: propertiesPanelConfig,
84631
84959
  apiLinkTarget,
84632
84960
  onInit
@@ -84694,7 +85022,10 @@ Please report this to https://github.com/markedjs/marked.`, e) {
84694
85022
  ...(editorProperties || {}),
84695
85023
  ariaLabel: 'Form Definition'
84696
85024
  },
84697
- additionalModules: [...(additionalModules || []), ...(editorAdditionalModules || [])]
85025
+ additionalModules: [...(additionalModules || []), ...(editorAdditionalModules || [])],
85026
+ ...(editorSlots ? {
85027
+ slots: editorSlots
85028
+ } : {})
84698
85029
  });
84699
85030
  formEditor.on('formField.add', ({
84700
85031
  formField
@@ -84757,7 +85088,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
84757
85088
  formViewer.destroy();
84758
85089
  formEditor.destroy();
84759
85090
  };
84760
- }, [additionalModules, editorAdditionalModules, editorProperties, emit, exporterConfig, propertiesPanelConfig, viewerAdditionalModules, viewerProperties]);
85091
+ }, [additionalModules, editorAdditionalModules, editorProperties, editorSlots, emit, exporterConfig, propertiesPanelConfig, viewerAdditionalModules, viewerProperties]);
84761
85092
 
84762
85093
  // initialize data through props
84763
85094
  p(() => {