@simai-studio/view 1.2.0 → 1.4.0

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.
Files changed (54) hide show
  1. package/README.md +5 -5
  2. package/dist/package-receipt.json +124 -124
  3. package/dist/set.json +1 -1
  4. package/dist/smart/view/component.json +19 -10
  5. package/dist/smart/view/component.json.gz +0 -0
  6. package/dist/smart/view/js/view.js +2 -2
  7. package/dist/smart/view/js/view.js.gz +0 -0
  8. package/dist/smart/view/js/view.min.js +1 -1
  9. package/dist/smart/view/js/view.min.js.gz +0 -0
  10. package/dist/smart/view/smart.manifest.json +14 -6
  11. package/dist/smart/view/smart.manifest.json.gz +0 -0
  12. package/dist/smart/view/static/default/open-record.html +1 -1
  13. package/dist/smart/view/static/default/open-record.html.gz +0 -0
  14. package/dist/smart/view/static/default/reference.html +1 -1
  15. package/dist/smart/view/static/default/reference.html.gz +0 -0
  16. package/dist/smart/view-flow/component.json +10 -2
  17. package/dist/smart/view-flow/component.json.gz +0 -0
  18. package/dist/smart/view-flow/css/view-flow.css +367 -0
  19. package/dist/smart/view-flow/css/view-flow.css.gz +0 -0
  20. package/dist/smart/view-flow/css/view-flow.min.css +1 -0
  21. package/dist/smart/view-flow/css/view-flow.min.css.gz +0 -0
  22. package/dist/smart/view-flow/js/view-flow.js +1977 -72
  23. package/dist/smart/view-flow/js/view-flow.js.gz +0 -0
  24. package/dist/smart/view-flow/js/view-flow.min.js +320 -197
  25. package/dist/smart/view-flow/js/view-flow.min.js.gz +0 -0
  26. package/dist/smart/view-flow/smart.manifest.json +11 -3
  27. package/dist/smart/view-flow/smart.manifest.json.gz +0 -0
  28. package/dist/smart/view-flow/static/default/ask.html +1 -1
  29. package/dist/smart/view-flow/static/default/ask.html.gz +0 -0
  30. package/dist/smart/view-flow/static/default/reference.html +2 -2
  31. package/dist/smart/view-flow/static/default/reference.html.gz +0 -0
  32. package/dist/smart/view-properties/component.json +15 -1
  33. package/dist/smart/view-properties/component.json.gz +0 -0
  34. package/dist/smart/view-properties/css/view-properties.css +384 -4
  35. package/dist/smart/view-properties/css/view-properties.css.gz +0 -0
  36. package/dist/smart/view-properties/css/view-properties.min.css +2 -1
  37. package/dist/smart/view-properties/css/view-properties.min.css.gz +0 -0
  38. package/dist/smart/view-properties/js/view-properties.js +1974 -69
  39. package/dist/smart/view-properties/js/view-properties.js.gz +0 -0
  40. package/dist/smart/view-properties/js/view-properties.min.js +553 -430
  41. package/dist/smart/view-properties/js/view-properties.min.js.gz +0 -0
  42. package/dist/smart/view-properties/smart.manifest.json +42 -4
  43. package/dist/smart/view-properties/smart.manifest.json.gz +0 -0
  44. package/dist/smart/view-properties/template/default.css +13 -2
  45. package/dist/smart/view-properties/template/default.css.gz +0 -0
  46. package/dist/smart/view-table/component.json +8 -1
  47. package/dist/smart/view-table/component.json.gz +0 -0
  48. package/dist/smart/view-table/js/view-table.js +393 -33
  49. package/dist/smart/view-table/js/view-table.js.gz +0 -0
  50. package/dist/smart/view-table/js/view-table.min.js +152 -139
  51. package/dist/smart/view-table/js/view-table.min.js.gz +0 -0
  52. package/dist/smart/view-table/smart.manifest.json +9 -2
  53. package/dist/smart/view-table/smart.manifest.json.gz +0 -0
  54. package/package.json +1 -1
@@ -441,6 +441,173 @@ function composeTime(original, text) {
441
441
 
442
442
  /***/ },
443
443
 
444
+ /***/ "ab3947ea3647"
445
+ (module, __webpack_exports__, __webpack_require__) {
446
+
447
+ __webpack_require__.a(module, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {
448
+ __webpack_require__.r(__webpack_exports__);
449
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
450
+ /* harmony export */ formatDecimal: () => (/* binding */ formatDecimal),
451
+ /* harmony export */ formatMoney: () => (/* binding */ formatMoney),
452
+ /* harmony export */ formatPercent: () => (/* binding */ formatPercent),
453
+ /* harmony export */ fractionDigits: () => (/* binding */ fractionDigits),
454
+ /* harmony export */ moneyParts: () => (/* binding */ moneyParts),
455
+ /* harmony export */ readDecimal: () => (/* binding */ readDecimal)
456
+ /* harmony export */ });
457
+ /* harmony import */ var _core_js_format_intl_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("15b4e93ff6ed");
458
+ var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_core_js_format_intl_js__WEBPACK_IMPORTED_MODULE_0__]);
459
+ var __webpack_async_dependencies_result__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
460
+ _core_js_format_intl_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_async_dependencies_result__[0];
461
+ // Decimal numbers as strings, never as floats (simai.property-view-port
462
+ // 1.18.0; Larena property types standard, notes of 2026-11-03: «Never a float
463
+ // on the wire»). What a person typed is read into a canonical decimal string,
464
+ // and a decimal, a money amount and a percent are shown in the page's language
465
+ // through Intl, which formats a string by its digits: «1500.10» never passes
466
+ // through a float on the way to «1 500,10 ₽». Pure, so the unit suite reads it
467
+ // without a browser; the View set draws the editors of money, percent and
468
+ // items with its own copy of the same rules.
469
+
470
+ const TYPED = /^([+-]?)(\d*)(?:[.,](\d*))?$/u; // Spaces a person or a formatter puts between groups of digits: the plain
471
+ // space, the no-break space and the narrow no-break space ru-RU writes, and
472
+ // the apostrophe some locales group with.
473
+
474
+ const GROUP_SPACES = /[\s  ']/gu;
475
+ /**
476
+ * What a person typed, read as a decimal: `{ok: true, value}` with the
477
+ * canonical string (an optional minus, the integer digits without leading
478
+ * zeros, the fraction digits as typed; null for nothing typed), or
479
+ * `{ok: false}` for text that is not a number. A comma and a point both
480
+ * separate the fraction. A JSON integer is read as its digits; a float is not
481
+ * a decimal and is refused rather than guessed at.
482
+ */
483
+
484
+ function readDecimal(text) {
485
+ if (text === null || typeof text === 'undefined') return {
486
+ ok: true,
487
+ value: null
488
+ };
489
+
490
+ if (typeof text === 'number') {
491
+ return Number.isSafeInteger(text) ? {
492
+ ok: true,
493
+ value: String(text)
494
+ } : {
495
+ ok: false
496
+ };
497
+ }
498
+
499
+ const plain = String(text).replace(GROUP_SPACES, '');
500
+ if (plain === '') return {
501
+ ok: true,
502
+ value: null
503
+ };
504
+ const match = TYPED.exec(plain);
505
+ if (!match) return {
506
+ ok: false
507
+ };
508
+ const [, sign, whole, fraction] = match;
509
+ if (whole === '' && (fraction ?? '') === '') return {
510
+ ok: false
511
+ };
512
+ const integer = whole.replace(/^0+(?=\d)/u, '') || '0';
513
+ const digits = fraction ?? '';
514
+ const zero = /^0*$/u.test(integer + digits);
515
+ return {
516
+ ok: true,
517
+ value: `${sign === '-' && !zero ? '-' : ''}${integer}${digits ? `.${digits}` : ''}`
518
+ };
519
+ }
520
+ /** How many digits a canonical decimal string has after its point. */
521
+
522
+ function fractionDigits(value) {
523
+ const at = String(value ?? '').indexOf('.');
524
+ return at === -1 ? 0 : String(value).length - at - 1;
525
+ } // A float a host sent anyway is shown, not refused: a cell is not the place to
526
+ // argue with a stored value. Only what reads as a decimal is formatted.
527
+
528
+ function decimalOf(value) {
529
+ if (typeof value === 'number') return Number.isFinite(value) ? String(value) : null;
530
+ const read = readDecimal(value);
531
+ return read.ok ? read.value : null;
532
+ }
533
+ /** A decimal string in the locale's digits, with every digit it has: «1 500,5». */
534
+
535
+
536
+ function formatDecimal(value, locale) {
537
+ const decimal = decimalOf(value);
538
+ if (decimal === null) return '';
539
+ const digits = Math.min(20, fractionDigits(decimal));
540
+ return (0,_core_js_format_intl_js__WEBPACK_IMPORTED_MODULE_0__.intlFormatter)('NumberFormat', locale, {
541
+ minimumFractionDigits: digits,
542
+ maximumFractionDigits: digits
543
+ }).format(decimal);
544
+ }
545
+ /** A money value as {amount, currency}; a field that fixes the currency takes a bare amount. */
546
+
547
+ function moneyParts(value, fixed) {
548
+ const currency = typeof fixed === 'string' && fixed ? fixed : null;
549
+
550
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
551
+ return {
552
+ amount: value.amount ?? null,
553
+ currency: currency || (value.currency ?? null)
554
+ };
555
+ }
556
+
557
+ if (value === null || typeof value === 'undefined' || value === '') return {
558
+ amount: null,
559
+ currency
560
+ };
561
+ return {
562
+ amount: value,
563
+ currency
564
+ };
565
+ }
566
+ /**
567
+ * An amount with its currency, as a person reads it: «1 500,50 ₽», «$1,500.50».
568
+ * The digits after the point are at least the currency's minor units (ISO
569
+ * 4217) and every digit the amount has. Without a currency, the amount alone.
570
+ */
571
+
572
+ function formatMoney(value, field = {}, locale = 'en') {
573
+ const {
574
+ amount,
575
+ currency
576
+ } = moneyParts(value, field.currency);
577
+ const decimal = decimalOf(amount);
578
+ if (decimal === null) return '';
579
+ if (!currency) return formatDecimal(decimal, locale);
580
+ const minor = (0,_core_js_format_intl_js__WEBPACK_IMPORTED_MODULE_0__.intlFormatter)('NumberFormat', locale, {
581
+ style: 'currency',
582
+ currency
583
+ }).resolvedOptions().maximumFractionDigits ?? 2;
584
+ const digits = Math.min(20, Math.max(minor, fractionDigits(decimal)));
585
+ return (0,_core_js_format_intl_js__WEBPACK_IMPORTED_MODULE_0__.intlFormatter)('NumberFormat', locale, {
586
+ style: 'currency',
587
+ currency,
588
+ currencyDisplay: 'narrowSymbol',
589
+ minimumFractionDigits: digits,
590
+ maximumFractionDigits: digits
591
+ }).format(decimal);
592
+ }
593
+ /** A percent, «12,5 %» or «12.5%»: the value is the percent ("20" is 20 %), never the share. */
594
+
595
+ function formatPercent(value, locale = 'en') {
596
+ const decimal = decimalOf(value);
597
+ if (decimal === null) return '';
598
+ const digits = Math.min(20, fractionDigits(decimal));
599
+ return (0,_core_js_format_intl_js__WEBPACK_IMPORTED_MODULE_0__.intlFormatter)('NumberFormat', locale, {
600
+ style: 'unit',
601
+ unit: 'percent',
602
+ minimumFractionDigits: digits,
603
+ maximumFractionDigits: digits
604
+ }).format(decimal);
605
+ }
606
+ __webpack_async_result__();
607
+ } catch(e) { __webpack_async_result__(e); } });
608
+
609
+ /***/ },
610
+
444
611
  /***/ "01ae054f01b4"
445
612
  (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
446
613
 
@@ -507,8 +674,9 @@ __webpack_require__.r(__webpack_exports__);
507
674
  /* harmony import */ var _datetime_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("9ce1a42b2a85");
508
675
  /* harmony import */ var _mask_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("dd6973f77245");
509
676
  /* harmony import */ var _html_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("01ae054f01b4");
510
- var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([lit__WEBPACK_IMPORTED_MODULE_0__, lit_directives_unsafe_html_js__WEBPACK_IMPORTED_MODULE_1__, _core_js_page_language__WEBPACK_IMPORTED_MODULE_3__]);
511
- ([lit__WEBPACK_IMPORTED_MODULE_0__, lit_directives_unsafe_html_js__WEBPACK_IMPORTED_MODULE_1__, _core_js_page_language__WEBPACK_IMPORTED_MODULE_3__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
677
+ /* harmony import */ var _decimal_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("ab3947ea3647");
678
+ var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([lit__WEBPACK_IMPORTED_MODULE_0__, lit_directives_unsafe_html_js__WEBPACK_IMPORTED_MODULE_1__, _core_js_page_language__WEBPACK_IMPORTED_MODULE_3__, _decimal_js__WEBPACK_IMPORTED_MODULE_8__]);
679
+ ([lit__WEBPACK_IMPORTED_MODULE_0__, lit_directives_unsafe_html_js__WEBPACK_IMPORTED_MODULE_1__, _core_js_page_language__WEBPACK_IMPORTED_MODULE_3__, _decimal_js__WEBPACK_IMPORTED_MODULE_8__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
512
680
  /* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(lit__WEBPACK_IMPORTED_MODULE_0__);
513
681
  /* harmony import */ var lit_directives_unsafe_html_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(lit_directives_unsafe_html_js__WEBPACK_IMPORTED_MODULE_1__);
514
682
  /* harmony import */ var _core_js_page_language__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__);
@@ -519,6 +687,7 @@ var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([lit_
519
687
 
520
688
 
521
689
 
690
+
522
691
  // The Framework's field renderers, addressed by a property type and a template
523
692
  // rather than by a control name.
524
693
  //
@@ -878,7 +1047,13 @@ const FILTER_RENDERERS = {
878
1047
  relation: renderEntityMultiSelectFilterControl,
879
1048
  lookup: renderEntityMultiSelectFilterControl,
880
1049
  file: renderFileFilterControl,
881
- color: renderColorFilterControl
1050
+ color: renderColorFilterControl,
1051
+ // The types a component set draws (property-view port 1.18.0): a money
1052
+ // amount and a percent are filtered as numbers (the host compares the
1053
+ // amount, as a decimal), and an items field by its number of rows.
1054
+ money: renderNumberFilterControl,
1055
+ percent: renderNumberFilterControl,
1056
+ items: renderNumberFilterControl
882
1057
  }; // What a field asks to be filtered by: its own declared control if it has one,
883
1058
  // otherwise its property type, otherwise text.
884
1059
 
@@ -1132,7 +1307,10 @@ const CELL_RENDERERS = {
1132
1307
  record: renderReferenceCell,
1133
1308
  relation: renderReferenceCell,
1134
1309
  lookup: renderLookupCell,
1135
- html: renderHtmlCell
1310
+ html: renderHtmlCell,
1311
+ money: renderMoneyCell,
1312
+ percent: renderPercentCell,
1313
+ items: renderItemsCell
1136
1314
  }; // A consumer found this on their stand: the words were written into the set, so
1137
1315
  // an English admin saw «Да». The set must not decide what a value is called in
1138
1316
  // anyone's language. They come from the field, which is where the rest of the
@@ -1192,6 +1370,41 @@ function renderChoiceCell(field, value) {
1192
1370
  function renderHostFormattedCell(field, value, host) {
1193
1371
  const formatted = host?.formatFieldValue?.(field, value);
1194
1372
  return typeof formatted === 'string' && formatted !== '' ? formatted : null;
1373
+ } // The types a component set draws (property-view port 1.18.0) have their
1374
+ // cells here, so a table shows them wherever the set's editors live. A host's
1375
+ // formatFieldValue wins, as for a date; otherwise the page's language:
1376
+ //
1377
+ // money {amount, currency} or a bare amount under a fixed `currency`;
1378
+ // «1 500,50 ₽», every digit the amount has and at least the
1379
+ // currency's minor units, formatted from the digits, never a float
1380
+ // percent a decimal string of the percent, «12,5 %»
1381
+ // items a list of rows; how many, «3 строки»
1382
+ //
1383
+ // A value that is not one of these shapes falls through to the plain value.
1384
+
1385
+
1386
+ function renderMoneyCell(field, value, host) {
1387
+ const formatted = renderHostFormattedCell(field, value, host);
1388
+ if (formatted !== null) return formatted;
1389
+ const text = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_8__.formatMoney)(scalarValue(value), field, (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageLocale)(host ?? null));
1390
+ return text || null;
1391
+ }
1392
+
1393
+ function renderPercentCell(field, value, host) {
1394
+ const formatted = renderHostFormattedCell(field, value, host);
1395
+ if (formatted !== null) return formatted;
1396
+ const text = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_8__.formatPercent)(scalarValue(value), (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageLocale)(host ?? null));
1397
+ return text || null;
1398
+ }
1399
+
1400
+ function renderItemsCell(field, value, host) {
1401
+ const formatted = renderHostFormattedCell(field, value, host);
1402
+ if (formatted !== null) return formatted;
1403
+ if (!Array.isArray(value)) return null;
1404
+ return value.length ? (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageWord)(SET_TEXT, 'rowCount', host ?? null, {
1405
+ component: SET_NAME,
1406
+ count: value.length
1407
+ }) : '';
1195
1408
  }
1196
1409
 
1197
1410
  function renderNumericCell(field, value, host) {
@@ -1366,10 +1579,14 @@ function renderPhoneEdit(field, value, host) {
1366
1579
  // Clearing a set password is not offered: an empty field means «keep».
1367
1580
  //
1368
1581
  // The typed text lives in the input and nowhere else: no `value` attribute on
1369
- // sf-input, no data-*, no text node, no log. «Показать» is an icon button that
1370
- // switches the input's type and says so with its pressed setting (aria-pressed); it changes the DOM
1371
- // directly, so a host's re-render (its attributes are static in the template)
1372
- // leaves the person's choice as it is.
1582
+ // sf-input, no data-*, no text node, no log. «Показать пароль» is an icon button
1583
+ // that switches the input's type and says what it will do next by its name and
1584
+ // icon: «Показать пароль» (visibility) while hidden, «Скрыть пароль»
1585
+ // (visibility_off) while shown. A toggle whose name changes is not a pressed
1586
+ // toggle (rule C12, point 3): it carries no aria-pressed and no pressed look,
1587
+ // or a reader would hear «Скрыть пароль, нажата». It changes the DOM directly,
1588
+ // so a host's re-render (its attributes are static in the template) leaves the
1589
+ // person's choice as it is.
1373
1590
 
1374
1591
 
1375
1592
  function isPasswordField(field) {
@@ -1385,13 +1602,13 @@ function passwordState(host, value) {
1385
1602
  return setText(host, passwordIsSet(value) ? 'passwordSet' : 'passwordUnset');
1386
1603
  }
1387
1604
 
1388
- function togglePasswordShown(event) {
1605
+ function togglePasswordShown(event, host) {
1389
1606
  const button = event.currentTarget;
1390
1607
  const input = button?.closest?.('.sf-field-password')?.querySelector?.('sf-input');
1391
1608
  if (!input) return;
1392
- const shown = button.getAttribute('pressed') === 'false';
1609
+ const shown = input.getAttribute('input-type') !== 'text';
1393
1610
  input.setAttribute('input-type', shown ? 'text' : 'password');
1394
- button.setAttribute('pressed', shown ? '' : 'false');
1611
+ button.setAttribute('aria-label', setText(host, shown ? 'hidePassword' : 'showPassword'));
1395
1612
  button.setAttribute('icon', shown ? 'visibility_off' : 'visibility');
1396
1613
  }
1397
1614
 
@@ -1427,9 +1644,8 @@ function renderPasswordEdit(field, value, host) {
1427
1644
  appearance="link"
1428
1645
  scheme="on-surface"
1429
1646
  icon="visibility"
1430
- pressed="false"
1431
1647
  aria-label=${setText(host, 'showPassword')}
1432
- @click=${togglePasswordShown}
1648
+ @click=${event => togglePasswordShown(event, host)}
1433
1649
  ></sf-button-icon>
1434
1650
  </span>
1435
1651
  `;
@@ -1692,29 +1908,98 @@ function renderStepperEdit(field, value, host) {
1692
1908
  @change=${write}
1693
1909
  ></sf-input-quantity>
1694
1910
  `;
1911
+ } // A number is a decimal (property-view port 1.18.0: «never a float on the
1912
+ // wire»). What is typed is read with a comma or a point and spaces between
1913
+ // groups. A number field whose value arrives as a string, or that declares
1914
+ // `precision`, is a decimal-string field: it writes the canonical decimal
1915
+ // string («1500.50»), never a float, and refuses more digits after the point
1916
+ // than `precision` allows. Any other number field writes a number, as before;
1917
+ // an integer field is unchanged. Text that is not a number is reported as a
1918
+ // masked string's incomplete entry is: through setFieldError, which holds the
1919
+ // save, and under the field once the person leaves it.
1920
+
1921
+
1922
+ function isDecimalStringField(field, value) {
1923
+ return (field.propertyType || field.type) === 'number' && (typeof value === 'string' || Number.isInteger(field.precision));
1695
1924
  }
1696
1925
 
1697
1926
  function renderNumberEdit(field, value, host) {
1698
1927
  if (isStepperField(field)) return renderStepperEdit(field, value, host);
1699
1928
  const decimal = (field.propertyType || field.type) === 'number';
1700
1929
  value = scalarValue(value);
1930
+
1931
+ if (!decimal) {
1932
+ return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
1933
+ <sf-input
1934
+ size=${EDIT_SIZE}
1935
+ appearance="bordered"
1936
+ name=${fieldName(field)}
1937
+ value=${value ?? ''}
1938
+ inputmode="numeric"
1939
+ ?required=${Boolean(field.required)}
1940
+ aria-label=${field.label || field.key || ''}
1941
+ @input=${event => {
1942
+ const next = event.target?.value ?? '';
1943
+ host.setFieldValue(field, next === '' ? null : Number(next));
1944
+ }}
1945
+ @change=${event => {
1946
+ const next = event.target?.value ?? '';
1947
+ host.setFieldValue(field, next === '' ? null : Number(next));
1948
+ }}
1949
+ ></sf-input>
1950
+ `;
1951
+ }
1952
+
1953
+ const asString = isDecimalStringField(field, value);
1954
+
1955
+ const write = (event, left) => {
1956
+ const input = event.currentTarget ?? event.target;
1957
+ const text = String(input?.value ?? '');
1958
+ const read = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_8__.readDecimal)(text);
1959
+ let message = null;
1960
+ if (!read.ok) message = setText(host, 'notNumber');else if (read.value !== null && Number.isInteger(field.precision) && (0,_decimal_js__WEBPACK_IMPORTED_MODULE_8__.fractionDigits)(read.value) > field.precision) {
1961
+ message = (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageWord)(SET_TEXT, 'precisionMax', host ?? null, {
1962
+ component: SET_NAME,
1963
+ count: field.precision
1964
+ });
1965
+ }
1966
+
1967
+ if (message) {
1968
+ if (left && input) {
1969
+ input.setAttribute('error-message', message);
1970
+ input.toggleAttribute('invalid', true);
1971
+ }
1972
+
1973
+ if (typeof host.setFieldError === 'function') {
1974
+ host.setFieldError(field, message);
1975
+ host.setFieldValue(field, text);
1976
+ } else {
1977
+ host.setFieldValue(field, undefined);
1978
+ }
1979
+
1980
+ return;
1981
+ }
1982
+
1983
+ if (input?.hasAttribute?.('invalid')) {
1984
+ input.toggleAttribute('invalid', false);
1985
+ input.removeAttribute('error-message');
1986
+ }
1987
+
1988
+ host.setFieldError?.(field, null);
1989
+ if (read.value === null) host.setFieldValue(field, null);else host.setFieldValue(field, asString ? read.value : Number(read.value));
1990
+ };
1991
+
1701
1992
  return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
1702
1993
  <sf-input
1703
1994
  size=${EDIT_SIZE}
1704
1995
  appearance="bordered"
1705
1996
  name=${fieldName(field)}
1706
1997
  value=${value ?? ''}
1707
- inputmode=${decimal ? 'decimal' : 'numeric'}
1998
+ inputmode="decimal"
1708
1999
  ?required=${Boolean(field.required)}
1709
2000
  aria-label=${field.label || field.key || ''}
1710
- @input=${event => {
1711
- const next = event.target?.value ?? '';
1712
- host.setFieldValue(field, next === '' ? null : Number(next));
1713
- }}
1714
- @change=${event => {
1715
- const next = event.target?.value ?? '';
1716
- host.setFieldValue(field, next === '' ? null : Number(next));
1717
- }}
2001
+ @input=${event => write(event, false)}
2002
+ @change=${event => write(event, true)}
1718
2003
  ></sf-input>
1719
2004
  `;
1720
2005
  } // A date control has no clock. `sf-input-date` declares a format and a date,
@@ -2157,7 +2442,14 @@ const SET_TEXT = {
2157
2442
  passwordUnset: 'Not set',
2158
2443
  passwordKeep: 'Set; type a new one to replace it',
2159
2444
  showPassword: 'Show password',
2160
- maskIncomplete: 'Complete the field'
2445
+ hidePassword: 'Hide password',
2446
+ maskIncomplete: 'Complete the field',
2447
+ notNumber: 'Enter a number',
2448
+ precisionMax: 'At most {n} digits after the point',
2449
+ rowCount: {
2450
+ one: '{n} row',
2451
+ other: '{n} rows'
2452
+ }
2161
2453
  },
2162
2454
  ru: {
2163
2455
  yes: 'Да',
@@ -2185,7 +2477,16 @@ const SET_TEXT = {
2185
2477
  passwordUnset: 'Не задан',
2186
2478
  passwordKeep: 'Задан; введите новый, чтобы заменить',
2187
2479
  showPassword: 'Показать пароль',
2188
- maskIncomplete: 'Заполните поле полностью'
2480
+ hidePassword: 'Скрыть пароль',
2481
+ maskIncomplete: 'Заполните поле полностью',
2482
+ notNumber: 'Введите число',
2483
+ precisionMax: 'Не больше {n} знаков после запятой',
2484
+ rowCount: {
2485
+ one: '{n} строка',
2486
+ few: '{n} строки',
2487
+ many: '{n} строк',
2488
+ other: '{n} строки'
2489
+ }
2189
2490
  }
2190
2491
  }; // The host's word wins, as it always did; the set's own fallback now follows
2191
2492
  // the page's language instead of being Russian whatever the page is. `host` is
@@ -2702,10 +3003,13 @@ function renderChoiceView(field, value) {
2702
3003
  const options = field.options || field.filter?.options || field.constraints?.options;
2703
3004
  const option = Array.isArray(options) ? options.find(item => String(item?.value) === String(value)) : null;
2704
3005
  if (!option) return lit__WEBPACK_IMPORTED_MODULE_0__.nothing;
2705
- const badge = (0,_helpers_option_badge_js__WEBPACK_IMPORTED_MODULE_2__.optionBadgeProps)(option);
3006
+ const badge = (0,_helpers_option_badge_js__WEBPACK_IMPORTED_MODULE_2__.optionBadgeProps)(option); // A table cell is a dense place: the badge keeps the tight side room
3007
+ // (sf-badge tight), as it had before sf-badge 1.3.0 widened the default.
3008
+
2706
3009
  return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
2707
3010
  <sf-badge
2708
3011
  line=${VIEW_LINE}
3012
+ tight
2709
3013
  appearance=${field.badgeAppearance ?? CELL_BADGE_APPEARANCE}
2710
3014
  scheme=${badge.scheme}
2711
3015
  style=${badge.rootStyle || lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
@@ -3031,12 +3335,13 @@ __webpack_require__.r(__webpack_exports__);
3031
3335
  /* harmony export */ modesOf: () => (/* binding */ modesOf)
3032
3336
  /* harmony export */ });
3033
3337
  // The registry of universal properties (owner, 2026-10-15): every property
3034
- // type the Framework renders, its variants and the parameters a field of it
3035
- // reads -- one list a host (Larena's fields and settings), the property
3036
- // workbench and the documentation read, instead of each learning the types
3037
- // from the renderers' source. Which modes a type has is not written here: it
3038
- // is read from the renderer maps themselves (modesOf), so the registry cannot
3039
- // claim a mode the set does not draw. A contract keeps the two the same.
3338
+ // type the Framework renders, or a component set renders beside it (`set`),
3339
+ // its variants and the parameters a field of it reads -- one list a host
3340
+ // (Larena's fields and settings), the property workbench and the documentation
3341
+ // read, instead of each learning the types from the renderers' source. Which
3342
+ // modes a type has is not written here: it is read from the renderer maps
3343
+ // themselves (modesOf), so the registry cannot claim a mode the set does not
3344
+ // draw. A contract keeps the two the same.
3040
3345
  //
3041
3346
  // `params` are the field keys the type's renderers read -- each one, and no
3042
3347
  // other (the probe field-renderer-params calls them with a field that records
@@ -3291,6 +3596,58 @@ const PROPERTY_TYPES = Object.freeze([{
3291
3596
  },
3292
3597
  variants: [],
3293
3598
  params: ['language', 'required', 'readonly']
3599
+ }, // The types a component set draws (property-view port 1.18.0; Larena
3600
+ // property types standard, notes of 2026-11-03): `set` names the set whose
3601
+ // components show and edit them -- the View set's sf-view-properties and
3602
+ // sf-view-flow -- and the Framework draws their table cells and filters
3603
+ // (money and percent as numbers, items by its number of rows). `params` are
3604
+ // the keys the type reads, in the set's renderers and in these. Every
3605
+ // number is a decimal string, never a float.
3606
+ {
3607
+ type: 'money',
3608
+ label: {
3609
+ ru: 'Деньги',
3610
+ en: 'Money'
3611
+ },
3612
+ set: 'view',
3613
+ variants: [],
3614
+ params: ['currency', 'min', 'max', 'required', 'readonly']
3615
+ }, {
3616
+ type: 'percent',
3617
+ label: {
3618
+ ru: 'Процент',
3619
+ en: 'Percent'
3620
+ },
3621
+ set: 'view',
3622
+ variants: [],
3623
+ params: ['min', 'max', 'required', 'readonly']
3624
+ }, {
3625
+ type: 'items',
3626
+ label: {
3627
+ ru: 'Строки',
3628
+ en: 'Rows'
3629
+ },
3630
+ set: 'view',
3631
+ variants: [],
3632
+ params: ['columns', 'minRows', 'maxRows', 'required', 'readonly']
3633
+ }, {
3634
+ type: 'compound',
3635
+ label: {
3636
+ ru: 'Составное',
3637
+ en: 'Compound'
3638
+ },
3639
+ set: 'view',
3640
+ variants: [],
3641
+ params: ['parts', 'required', 'readonly']
3642
+ }, {
3643
+ type: 'ru.requisites',
3644
+ label: {
3645
+ ru: 'Реквизиты',
3646
+ en: 'Requisites (Russia)'
3647
+ },
3648
+ set: 'view',
3649
+ variants: [],
3650
+ params: ['parts', 'required', 'readonly']
3294
3651
  }]); // The modes a type has, read from the renderer maps: view and edit (a record),
3295
3652
  // cell (a table) and filter -- `own` when the set has a filter control for the
3296
3653
  // type, `text` when a filter falls back to a text search.
@@ -7583,6 +7940,226 @@ function fieldConditions(field, values) {
7583
7940
 
7584
7941
  /***/ },
7585
7942
 
7943
+ /***/ "f44b979883f0"
7944
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
7945
+
7946
+ __webpack_require__.r(__webpack_exports__);
7947
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
7948
+ /* harmony export */ add: () => (/* binding */ add),
7949
+ /* harmony export */ compare: () => (/* binding */ compare),
7950
+ /* harmony export */ decimalString: () => (/* binding */ decimalString),
7951
+ /* harmony export */ editableDecimal: () => (/* binding */ editableDecimal),
7952
+ /* harmony export */ formatDecimal: () => (/* binding */ formatDecimal),
7953
+ /* harmony export */ fractionDigits: () => (/* binding */ fractionDigits),
7954
+ /* harmony export */ multiply: () => (/* binding */ multiply),
7955
+ /* harmony export */ readDecimal: () => (/* binding */ readDecimal),
7956
+ /* harmony export */ round: () => (/* binding */ round),
7957
+ /* harmony export */ share: () => (/* binding */ share),
7958
+ /* harmony export */ toDecimal: () => (/* binding */ toDecimal)
7959
+ /* harmony export */ });
7960
+ // Decimal numbers as strings, never as floats (Larena property types standard,
7961
+ // notes of 2026-11-03: «Arithmetic is on decimal digits, never on floats»;
7962
+ // «Never a float on the wire»). A money amount, a percent and every cell a row
7963
+ // computes are read, multiplied, summed and rounded here on BigInt units, so
7964
+ // 0.1 + 0.2 is 0.3 and 2 499,99 stays 2 499,99 however many rows add up to it.
7965
+ //
7966
+ // A decimal is {units, scale}: the value is units / 10^scale. The canonical
7967
+ // string has an optional minus, the integer digits without leading zeros and
7968
+ // the fraction digits as written ("1500.50", "0.5", "-3"); "-0" is "0".
7969
+ const TYPED = /^([+-]?)(\d*)(?:[.,](\d*))?$/u; // Spaces a person or a formatter puts between groups of digits: the plain
7970
+ // space, the no-break space and the narrow no-break space ru-RU writes.
7971
+
7972
+ const GROUP_SPACES = /[\s   ']/gu;
7973
+ /**
7974
+ * What a person typed, read as a decimal: `{ok: true, value}` with the
7975
+ * canonical string (null for nothing typed), or `{ok: false}` for text that is
7976
+ * not a number. A comma and a point both separate the fraction; spaces between
7977
+ * groups go.
7978
+ */
7979
+
7980
+ function readDecimal(text) {
7981
+ if (text === null || typeof text === 'undefined') return {
7982
+ ok: true,
7983
+ value: null
7984
+ };
7985
+
7986
+ if (typeof text === 'number') {
7987
+ // A JSON integer is taken as its digits (property types standard §5); a
7988
+ // float is not a decimal and is refused rather than guessed at.
7989
+ return Number.isSafeInteger(text) ? {
7990
+ ok: true,
7991
+ value: String(text)
7992
+ } : {
7993
+ ok: false
7994
+ };
7995
+ }
7996
+
7997
+ const plain = String(text).replace(GROUP_SPACES, '');
7998
+ if (plain === '') return {
7999
+ ok: true,
8000
+ value: null
8001
+ };
8002
+ const match = TYPED.exec(plain);
8003
+ if (!match) return {
8004
+ ok: false
8005
+ };
8006
+ const [, sign, whole, fraction] = match;
8007
+ if (whole === '' && (fraction ?? '') === '') return {
8008
+ ok: false
8009
+ };
8010
+ const integer = whole.replace(/^0+(?=\d)/u, '') || '0';
8011
+ const digits = fraction ?? '';
8012
+ const zero = /^0*$/u.test(integer + digits);
8013
+ const value = `${sign === '-' && !zero ? '-' : ''}${integer}${digits ? `.${digits}` : ''}`;
8014
+ return {
8015
+ ok: true,
8016
+ value
8017
+ };
8018
+ }
8019
+ /** The decimal of a canonical string or a JSON integer, or null. */
8020
+
8021
+ function toDecimal(value) {
8022
+ if (value && typeof value === 'object' && typeof value.units === 'bigint') return value;
8023
+ const read = readDecimal(value);
8024
+ if (!read.ok || read.value === null) return null;
8025
+ const negative = read.value.startsWith('-');
8026
+ const [whole, fraction = ''] = read.value.replace('-', '').split('.');
8027
+ const units = BigInt(whole + fraction) * (negative ? -1n : 1n);
8028
+ return {
8029
+ units,
8030
+ scale: fraction.length
8031
+ };
8032
+ }
8033
+ /** How many digits a decimal string has after its point. */
8034
+
8035
+ function fractionDigits(value) {
8036
+ const read = readDecimal(value);
8037
+ if (!read.ok || read.value === null) return 0;
8038
+ const at = read.value.indexOf('.');
8039
+ return at === -1 ? 0 : read.value.length - at - 1;
8040
+ }
8041
+ const POWERS = new Map();
8042
+
8043
+ const power = n => {
8044
+ if (!POWERS.has(n)) POWERS.set(n, 10n ** BigInt(n));
8045
+ return POWERS.get(n);
8046
+ };
8047
+
8048
+ function rescale(decimal, scale) {
8049
+ return decimal.scale === scale ? decimal : {
8050
+ units: decimal.units * power(scale - decimal.scale),
8051
+ scale
8052
+ };
8053
+ }
8054
+
8055
+ function multiply(a, b) {
8056
+ return {
8057
+ units: a.units * b.units,
8058
+ scale: a.scale + b.scale
8059
+ };
8060
+ }
8061
+ function add(a, b) {
8062
+ const scale = Math.max(a.scale, b.scale);
8063
+ return {
8064
+ units: rescale(a, scale).units + rescale(b, scale).units,
8065
+ scale
8066
+ };
8067
+ }
8068
+ /** A share: 20 percent is 0.2 (property types standard, rows: «A percent operand counts as its share»). */
8069
+
8070
+ function share(decimal) {
8071
+ return {
8072
+ units: decimal.units,
8073
+ scale: decimal.scale + 2
8074
+ };
8075
+ }
8076
+ /** Rounded half away from zero to `scale` digits after the point. */
8077
+
8078
+ function round(decimal, scale) {
8079
+ if (decimal.scale <= scale) return rescale(decimal, scale);
8080
+ const divisor = power(decimal.scale - scale);
8081
+ const negative = decimal.units < 0n;
8082
+ const magnitude = negative ? -decimal.units : decimal.units;
8083
+ let units = magnitude / divisor;
8084
+ if (magnitude % divisor * 2n >= divisor) units += 1n;
8085
+ return {
8086
+ units: negative ? -units : units,
8087
+ scale
8088
+ };
8089
+ }
8090
+ function compare(a, b) {
8091
+ const scale = Math.max(a.scale, b.scale);
8092
+ const left = rescale(a, scale).units;
8093
+ const right = rescale(b, scale).units;
8094
+ return left === right ? 0 : left < right ? -1 : 1;
8095
+ }
8096
+ /** The canonical string of a decimal, with exactly its scale's digits after the point. */
8097
+
8098
+ function decimalString(decimal) {
8099
+ const negative = decimal.units < 0n;
8100
+ const digits = (negative ? -decimal.units : decimal.units).toString().padStart(decimal.scale + 1, '0');
8101
+ const whole = decimal.scale ? digits.slice(0, -decimal.scale) : digits;
8102
+ const fraction = decimal.scale ? digits.slice(-decimal.scale) : '';
8103
+ const zero = decimal.units === 0n;
8104
+ return `${negative && !zero ? '-' : ''}${whole}${fraction ? `.${fraction}` : ''}`;
8105
+ } // The separators of a locale, read once from Intl and kept: a decimal is
8106
+ // formatted from its digits, so no amount passes through a float to be shown.
8107
+
8108
+ const SEPARATORS = new Map();
8109
+
8110
+ function separators(locale) {
8111
+ if (!SEPARATORS.has(locale)) {
8112
+ let group = ' ';
8113
+ let point = '.';
8114
+
8115
+ try {
8116
+ for (const part of new Intl.NumberFormat(locale).formatToParts(12345.6)) {
8117
+ if (part.type === 'group') group = part.value;
8118
+ if (part.type === 'decimal') point = part.value;
8119
+ }
8120
+ } catch {// An unknown locale keeps the defaults.
8121
+ }
8122
+
8123
+ SEPARATORS.set(locale, {
8124
+ group,
8125
+ point
8126
+ });
8127
+ }
8128
+
8129
+ return SEPARATORS.get(locale);
8130
+ }
8131
+ /**
8132
+ * A decimal string as a person reads it in `locale`: groups of three, the
8133
+ * locale's point, and at least `minFraction` digits after it («1 500,50»).
8134
+ * Groups start at four digits, as the standard reads money («1 500,50 ₽»).
8135
+ */
8136
+
8137
+
8138
+ function formatDecimal(value, locale, {
8139
+ minFraction = 0
8140
+ } = {}) {
8141
+ const decimal = toDecimal(value);
8142
+ if (!decimal) return '';
8143
+ const text = decimalString(decimal.scale < minFraction ? rescale(decimal, minFraction) : decimal);
8144
+ const negative = text.startsWith('-');
8145
+ const [whole, fraction] = text.replace('-', '').split('.');
8146
+ const {
8147
+ group,
8148
+ point
8149
+ } = separators(locale);
8150
+ const grouped = whole.replace(/\B(?=(\d{3})+(?!\d))/gu, group);
8151
+ return `${negative ? '−' : ''}${grouped}${fraction ? `${point}${fraction}` : ''}`;
8152
+ }
8153
+ /** A decimal string as typed in an input: the locale's point, no groups («1500,5»). */
8154
+
8155
+ function editableDecimal(value, locale) {
8156
+ const read = readDecimal(value);
8157
+ if (!read.ok || read.value === null) return '';
8158
+ return read.value.replace('.', separators(locale).point);
8159
+ }
8160
+
8161
+ /***/ },
8162
+
7586
8163
  /***/ "62c5c417c97d"
7587
8164
  (module, __webpack_exports__, __webpack_require__) {
7588
8165
 
@@ -7593,10 +8170,12 @@ __webpack_require__.r(__webpack_exports__);
7593
8170
  /* harmony export */ });
7594
8171
  /* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("2a080a730149");
7595
8172
  /* harmony import */ var _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("e5483002f3ea");
7596
- var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([lit__WEBPACK_IMPORTED_MODULE_0__, _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_1__]);
7597
- ([lit__WEBPACK_IMPORTED_MODULE_0__, _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_1__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
8173
+ /* harmony import */ var _set_fields_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("db94c32f22be");
8174
+ var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([lit__WEBPACK_IMPORTED_MODULE_0__, _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_1__, _set_fields_js__WEBPACK_IMPORTED_MODULE_2__]);
8175
+ ([lit__WEBPACK_IMPORTED_MODULE_0__, _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_1__, _set_fields_js__WEBPACK_IMPORTED_MODULE_2__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
7598
8176
  /* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(lit__WEBPACK_IMPORTED_MODULE_0__);
7599
8177
 
8178
+
7600
8179
  // One field's value, shown or edited, drawn by the SIMAI Framework field
7601
8180
  // renderers. Moved out of the record component's template (sf-view-properties
7602
8181
  // 1.10.0) so that every view of the set that draws a field draws it the same
@@ -7634,12 +8213,27 @@ function renderFieldValue(context, field, editing, {
7634
8213
  setFieldOptionSearch: (target, text) => context.component.setFieldOptionSearch(target, text),
7635
8214
  loadFieldOptions: (target, request) => context.component.loadFieldOptions(target, request)
7636
8215
  } : {})
7637
- }; // A datetime and a time of day are the renderer set's: sf-input-date in
8216
+ }; // Money, a percent, rows and the compound fields are the set's own
8217
+ // (js/set-fields.js, Larena addendum of 2026-11-03): drawn from Framework
8218
+ // controls, with the edit host above, before the Framework renderers are
8219
+ // asked for a type they do not draw.
8220
+
8221
+ const own = (0,_set_fields_js__WEBPACK_IMPORTED_MODULE_2__.renderSetField)(field, context.changed.has(key) && editing ? context.changed.get(key) : field.value, editing, editHost, {
8222
+ node: context.component,
8223
+ size: context.size,
8224
+ viewHost: context.viewHost,
8225
+ disabled
8226
+ });
8227
+
8228
+ if (own !== null) {
8229
+ return own === lit__WEBPACK_IMPORTED_MODULE_0__.nothing ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-property-view-empty color-on-surface-variant">${context.emptyText}</span>` : own;
8230
+ } // A datetime and a time of day are the renderer set's: sf-input-date in
7638
8231
  // mode datetime and time, one control each (SIMAI Framework duplication
7639
8232
  // audit A-14). This view drew its own pair -- the day in a datepicker and
7640
8233
  // the time in a masked field -- which cut the day short in a half-width
7641
8234
  // field and held half-typed entries of its own.
7642
8235
 
8236
+
7643
8237
  const content = editing ? (0,_field_renderers_index_js__WEBPACK_IMPORTED_MODULE_1__.renderEditField)(field, context.changed.has(key) ? context.changed.get(key) : field.value, editHost, // A field its condition turns off is drawn disabled where the set
7644
8238
  // draws disabled apart from read-only (a choice as buttons).
7645
8239
  {
@@ -7694,50 +8288,1352 @@ __webpack_async_result__();
7694
8288
 
7695
8289
  /***/ },
7696
8290
 
7697
- /***/ "40b137e60526"
7698
- (module, __webpack_exports__, __webpack_require__) {
8291
+ /***/ "d69ebe7e288e"
8292
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
7699
8293
 
7700
- __webpack_require__.a(module, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {
7701
8294
  __webpack_require__.r(__webpack_exports__);
7702
8295
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
7703
- /* harmony export */ renderPropertyViewTemplate: () => (/* binding */ renderPropertyViewTemplate)
8296
+ /* harmony export */ currencyOf: () => (/* binding */ currencyOf),
8297
+ /* harmony export */ formatMoney: () => (/* binding */ formatMoney),
8298
+ /* harmony export */ moneyParts: () => (/* binding */ moneyParts),
8299
+ /* harmony export */ percentText: () => (/* binding */ percentText)
7704
8300
  /* harmony export */ });
7705
- /* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("2a080a730149");
7706
- /* harmony import */ var _default_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("9e9dad7bcc09");
7707
- /* harmony import */ var _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("e5483002f3ea");
7708
- /* harmony import */ var _field_value_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("62c5c417c97d");
7709
- var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([lit__WEBPACK_IMPORTED_MODULE_0__, _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__, _field_value_js__WEBPACK_IMPORTED_MODULE_3__]);
7710
- ([lit__WEBPACK_IMPORTED_MODULE_0__, _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__, _field_value_js__WEBPACK_IMPORTED_MODULE_3__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
7711
- /* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(lit__WEBPACK_IMPORTED_MODULE_0__);
8301
+ /* harmony import */ var _decimal_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("f44b979883f0");
8302
+ // Money and percent as a person reads them, from decimal strings, never a
8303
+ // float: the currency's sign and minor units come from Intl, the digits from
8304
+ // ./decimal.js. Pure, so the unit suite reads it without a browser.
7712
8305
 
8306
+ const CURRENCY = new Map();
8307
+ /** {sign, before, minor}: the sign a locale writes, whether before the amount, and the ISO 4217 minor units. */
7713
8308
 
8309
+ function currencyOf(code, locale) {
8310
+ const id = `${code}|${locale}`;
7714
8311
 
7715
- // The arrangement, drawn in the component's own light DOM. Not in a shadow root:
7716
- // the field controls are Smart elements whose stylesheets are document-level, and
7717
- // a document stylesheet does not cross a shadow boundary. sf-view slots its
7718
- // children for exactly this reason and says so beside the slot; the first version
7719
- // of this composite built them inside a shadow root and every control came out
7720
- // with its markup and none of its CSS.
7721
- // While the view is being configured every entry is listed, hidden and rare ones
7722
- // included: a hidden field a person cannot see is a field they cannot show again,
7723
- // and «показать редкие поля» is a reading choice rather than part of the
7724
- // arrangement being edited.
8312
+ if (!CURRENCY.has(id)) {
8313
+ let sign = code;
8314
+ let before = false;
8315
+ let minor = 2;
7725
8316
 
7726
- function listed(context, entries) {
7727
- return context.configuring ? entries ?? [] : context.visible(entries);
7728
- } // The chooser names the layers this person may write and nothing else. A layer
7729
- // they may not write is drawn disabled with the host's own reason on it rather
7730
- // than left out, because a «Для всех» that is simply absent reads as a feature
7731
- // the product does not have.
7732
- // The controls of the arranging mode live in the bar at the foot (owner,
7733
- // 2026-10-08), where saving, cancelling and deleting live when a group is being
7734
- // edited: the foot is where a mode's own answers belong, and a band of them
7735
- // under the head pushed the record down by a row it did not need.
8317
+ try {
8318
+ const format = new Intl.NumberFormat(locale, {
8319
+ style: 'currency',
8320
+ currency: code,
8321
+ currencyDisplay: 'narrowSymbol'
8322
+ });
8323
+ const parts = format.formatToParts(1);
8324
+ const at = parts.findIndex(part => part.type === 'currency');
8325
+ sign = parts[at]?.value ?? code;
8326
+ before = at < parts.findIndex(part => part.type === 'integer');
8327
+ minor = format.resolvedOptions().maximumFractionDigits;
8328
+ } catch {// A code Intl does not know keeps its letters and two minor digits.
8329
+ }
7736
8330
 
8331
+ CURRENCY.set(id, {
8332
+ sign,
8333
+ before,
8334
+ minor
8335
+ });
8336
+ }
7737
8337
 
7738
- function renderConfigureBar(context) {
7739
- if (!context.canConfigureView) return lit__WEBPACK_IMPORTED_MODULE_0__.nothing; // Not configuring: nothing is drawn. Entering is the «⋯» menu's, as the mockup
7740
- // has it -- a standalone «Настроить вид» link stood as its own band under the
8338
+ return CURRENCY.get(id);
8339
+ }
8340
+ /** An amount with its currency, as a person reads it: «1 500,50 ₽», «$1,500.50». */
8341
+
8342
+ function formatMoney(amount, code, locale) {
8343
+ if (!code) return (0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.formatDecimal)(amount, locale);
8344
+ const {
8345
+ sign,
8346
+ before,
8347
+ minor
8348
+ } = currencyOf(code, locale);
8349
+ const number = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.formatDecimal)(amount, locale, {
8350
+ minFraction: minor
8351
+ });
8352
+ if (!number) return '';
8353
+ return before ? `${sign}${number}` : `${number} ${sign}`;
8354
+ }
8355
+ /** A money value as {amount, currency}; a field that fixes the currency takes a bare amount. */
8356
+
8357
+ function moneyParts(value, fixed) {
8358
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
8359
+ return {
8360
+ amount: value.amount ?? null,
8361
+ currency: fixed || (value.currency ?? null)
8362
+ };
8363
+ }
8364
+
8365
+ if (value === null || typeof value === 'undefined' || value === '') return {
8366
+ amount: null,
8367
+ currency: fixed || null
8368
+ };
8369
+ return {
8370
+ amount: value,
8371
+ currency: fixed || null
8372
+ };
8373
+ }
8374
+ function percentText(value, locale) {
8375
+ const number = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.formatDecimal)(value, locale);
8376
+ if (!number) return ''; // ru-RU writes «12,5 %», en «12.5%»: the space is the locale's, read from Intl.
8377
+
8378
+ let spaced = false;
8379
+
8380
+ try {
8381
+ spaced = new Intl.NumberFormat(locale, {
8382
+ style: 'percent'
8383
+ }).formatToParts(0.5).some(part => part.type === 'literal' && /\s/u.test(part.value));
8384
+ } catch {
8385
+ spaced = false;
8386
+ }
8387
+
8388
+ return `${number}${spaced ? ' ' : ''}%`;
8389
+ }
8390
+
8391
+ /***/ },
8392
+
8393
+ /***/ "06dfc7b3b9d9"
8394
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
8395
+
8396
+ __webpack_require__.r(__webpack_exports__);
8397
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
8398
+ /* harmony export */ REQUISITE_PARTS: () => (/* binding */ REQUISITE_PARTS),
8399
+ /* harmony export */ innValid: () => (/* binding */ innValid),
8400
+ /* harmony export */ ogrnValid: () => (/* binding */ ogrnValid),
8401
+ /* harmony export */ requisiteErrors: () => (/* binding */ requisiteErrors)
8402
+ /* harmony export */ });
8403
+ // The checks of Russian requisites (Larena property types standard, notes of
8404
+ // 2026-11-03, `ru.requisites@1`): each part on its own, and the parts that go
8405
+ // together, together. The server checks the same and is the authority; these
8406
+ // are here so a person sees a mistyped ИНН under the field instead of a refused
8407
+ // save after it.
8408
+ //
8409
+ // Every check answers the key of the words that explain the mistake, or null.
8410
+ const REQUISITE_PARTS = Object.freeze(['inn', 'kpp', 'ogrn', 'bik', 'account', 'corr_account']);
8411
+
8412
+ const digitsOf = text => [...text].map(Number);
8413
+
8414
+ const weighted = (digits, weights) => weights.reduce((sum, weight, index) => sum + weight * digits[index], 0);
8415
+
8416
+ function innValid(inn) {
8417
+ if (!/^\d{10}$|^\d{12}$/u.test(inn)) return false;
8418
+ const d = digitsOf(inn);
8419
+ if (inn.length === 10) return weighted(d, [2, 4, 10, 3, 5, 9, 4, 6, 8]) % 11 % 10 === d[9];
8420
+ const eleventh = weighted(d, [7, 2, 4, 10, 3, 5, 9, 4, 6, 8]) % 11 % 10;
8421
+ const twelfth = weighted(d, [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8]) % 11 % 10;
8422
+ return eleventh === d[10] && twelfth === d[11];
8423
+ }
8424
+ function ogrnValid(ogrn) {
8425
+ if (!/^\d{13}$|^\d{15}$/u.test(ogrn)) return false;
8426
+ const body = BigInt(ogrn.slice(0, -1));
8427
+ const modulus = ogrn.length === 13 ? 11n : 13n;
8428
+ return Number(body % modulus % 10n) === Number(ogrn.at(-1));
8429
+ } // An account is checked with the БИК by the Bank of Russia key: the three
8430
+ // digits that come before it, then its twenty, weighted 7, 1, 3 in turn, add up
8431
+ // to a multiple of ten. A settlement account takes the БИК's last three digits;
8432
+ // a correspondent account takes «0» and the БИК's fifth and sixth.
8433
+
8434
+ function accountKeyValid(prefix, account) {
8435
+ const digits = digitsOf(prefix + account);
8436
+ const sum = digits.reduce((total, digit, index) => total + digit * [7, 1, 3][index % 3], 0);
8437
+ return sum % 10 === 0;
8438
+ }
8439
+ /** The mistakes of a requisites value, part by part: {inn: 'innWrong', …}. */
8440
+
8441
+
8442
+ function requisiteErrors(value, parts = REQUISITE_PARTS) {
8443
+ const errors = {};
8444
+
8445
+ const has = part => parts.includes(part);
8446
+
8447
+ const of = part => String(value?.[part] ?? '');
8448
+
8449
+ const inn = of('inn');
8450
+ const kpp = of('kpp');
8451
+ const ogrn = of('ogrn');
8452
+ const bik = of('bik');
8453
+ const account = of('account');
8454
+ const corr = of('corr_account');
8455
+
8456
+ if (has('inn')) {
8457
+ // The ИНН is required (the standard): a value without one is no value.
8458
+ if (!inn) errors.inn = 'innRequired';else if (!/^\d{10}$|^\d{12}$/u.test(inn)) errors.inn = 'innLength';else if (!innValid(inn)) errors.inn = 'innWrong';
8459
+ }
8460
+
8461
+ const person = inn.length === 12;
8462
+ const organization = inn.length === 10;
8463
+
8464
+ if (has('kpp') && kpp) {
8465
+ if (!/^\d{4}[\dA-Z]{2}\d{3}$/u.test(kpp)) errors.kpp = 'kppWrong';else if (person) errors.kpp = 'kppPerson';
8466
+ }
8467
+
8468
+ if (has('ogrn') && ogrn) {
8469
+ if (!/^\d{13}$|^\d{15}$/u.test(ogrn)) errors.ogrn = 'ogrnLength';else if (!ogrnValid(ogrn)) errors.ogrn = 'ogrnWrong';else if (organization && ogrn.length !== 13) errors.ogrn = 'ogrnOrganization';else if (person && ogrn.length !== 15) errors.ogrn = 'ogrnPerson';
8470
+ }
8471
+
8472
+ const bikRight = /^04\d{7}$/u.test(bik);
8473
+ if (has('bik') && bik && !bikRight) errors.bik = 'bikWrong';
8474
+
8475
+ if (has('account') && account) {
8476
+ if (!/^\d{20}$/u.test(account)) errors.account = 'accountLength';else if (bikRight && !accountKeyValid(bik.slice(-3), account)) errors.account = 'accountKey';
8477
+ }
8478
+
8479
+ if (has('corr_account') && corr) {
8480
+ if (!/^\d{20}$/u.test(corr)) errors.corr_account = 'accountLength';else if (!corr.startsWith('301')) errors.corr_account = 'corrStart';else if (bikRight && !accountKeyValid(`0${bik.slice(4, 6)}`, corr)) errors.corr_account = 'accountKey';
8481
+ }
8482
+
8483
+ return errors;
8484
+ }
8485
+
8486
+ /***/ },
8487
+
8488
+ /***/ "ebc72103d8b6"
8489
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
8490
+
8491
+ __webpack_require__.r(__webpack_exports__);
8492
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
8493
+ /* harmony export */ NUMERIC: () => (/* binding */ NUMERIC),
8494
+ /* harmony export */ cellDecimal: () => (/* binding */ cellDecimal),
8495
+ /* harmony export */ columnCurrency: () => (/* binding */ columnCurrency),
8496
+ /* harmony export */ columnOf: () => (/* binding */ columnOf),
8497
+ /* harmony export */ columnsOf: () => (/* binding */ columnsOf),
8498
+ /* harmony export */ computeRow: () => (/* binding */ computeRow),
8499
+ /* harmony export */ rowTotals: () => (/* binding */ rowTotals),
8500
+ /* harmony export */ rowsOf: () => (/* binding */ rowsOf)
8501
+ /* harmony export */ });
8502
+ /* harmony import */ var _decimal_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("f44b979883f0");
8503
+ /* harmony import */ var _money_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("d69ebe7e288e");
8504
+
8505
+ // Rows over columns (Larena property types standard, notes of 2026-11-03,
8506
+ // `items@1`): the columns as the set reads them, the computed cells of a row
8507
+ // and the totals under summed columns, on decimal strings. Pure, so the unit
8508
+ // suite reads it without a browser.
8509
+
8510
+ const NUMERIC = new Set(['integer', 'number', 'percent', 'money']); // A column as the set reads it: its settings beside its own keys, its type
8511
+ // under the name the renderers address (`propertyType`).
8512
+
8513
+ function columnOf(column) {
8514
+ const {
8515
+ settings,
8516
+ ...own
8517
+ } = column ?? {};
8518
+ const type = own.propertyType || own.type;
8519
+ return { ...(settings && typeof settings === 'object' ? settings : {}),
8520
+ ...own,
8521
+ propertyType: type,
8522
+ type
8523
+ };
8524
+ }
8525
+ function columnsOf(field) {
8526
+ return (Array.isArray(field.columns) ? field.columns : []).map(columnOf).filter(column => column.key);
8527
+ }
8528
+ function rowsOf(value) {
8529
+ return Array.isArray(value) ? value.map(row => row && typeof row === 'object' ? row : {}) : [];
8530
+ } // The decimal a numeric cell holds, or null.
8531
+
8532
+ function cellDecimal(column, cell) {
8533
+ if (cell === null || typeof cell === 'undefined' || cell === '') return null;
8534
+ if (column.propertyType === 'money') return (0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.toDecimal)((0,_money_js__WEBPACK_IMPORTED_MODULE_1__.moneyParts)(cell, column.currency).amount);
8535
+ return (0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.toDecimal)(cell);
8536
+ } // The currency a money column's cells are in: its own, else the one money
8537
+ // operand's when it is computed.
8538
+
8539
+ function columnCurrency(column, columns) {
8540
+ if (column.currency) return column.currency;
8541
+
8542
+ if (column.compute?.of) {
8543
+ const operand = columns.find(one => column.compute.of.includes(one.key) && one.propertyType === 'money');
8544
+ return operand?.currency ?? null;
8545
+ }
8546
+
8547
+ return null;
8548
+ }
8549
+ /**
8550
+ * A row with its computed cells worked out from the cells typed: a product of
8551
+ * two or three operands, a percent counting as its share, rounded half away
8552
+ * from zero to the currency's minor units or the column's `scale` (2 by
8553
+ * default). A computed cell whose operands are not all there is no cell. The
8554
+ * keys follow the columns, the computed ones last. The server works the same
8555
+ * out and is the authority.
8556
+ */
8557
+
8558
+ function computeRow(row, columns, locale = 'en') {
8559
+ const typed = {};
8560
+ const computed = {};
8561
+
8562
+ for (const column of columns) {
8563
+ if (column.compute) continue;
8564
+ if (Object.hasOwn(row, column.key) && row[column.key] !== null && row[column.key] !== '') typed[column.key] = row[column.key];
8565
+ }
8566
+
8567
+ for (const column of columns) {
8568
+ if (!column.compute || column.compute.op !== 'multiply' || !Array.isArray(column.compute.of)) continue;
8569
+ let product = null;
8570
+ let currency = null;
8571
+
8572
+ for (const key of column.compute.of) {
8573
+ const operand = columns.find(one => one.key === key);
8574
+ const decimal = operand ? cellDecimal(operand, typed[key]) : null;
8575
+
8576
+ if (!decimal) {
8577
+ product = null;
8578
+ break;
8579
+ }
8580
+
8581
+ if (operand.propertyType === 'money') currency = (0,_money_js__WEBPACK_IMPORTED_MODULE_1__.moneyParts)(typed[key], operand.currency).currency;
8582
+ const factor = operand.propertyType === 'percent' ? (0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.share)(decimal) : decimal;
8583
+ product = product ? (0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.multiply)(product, factor) : factor;
8584
+ }
8585
+
8586
+ if (!product) continue;
8587
+
8588
+ if (column.propertyType === 'money') {
8589
+ const code = column.currency || currency;
8590
+ const scale = code ? (0,_money_js__WEBPACK_IMPORTED_MODULE_1__.currencyOf)(code, locale).minor : 2;
8591
+ computed[column.key] = {
8592
+ amount: (0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.decimalString)((0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.round)(product, scale)),
8593
+ currency: code
8594
+ };
8595
+ } else {
8596
+ const scale = column.propertyType === 'integer' ? 0 : Number.isInteger(column.scale) ? column.scale : 2;
8597
+ computed[column.key] = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.decimalString)((0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.round)(product, scale));
8598
+ }
8599
+ }
8600
+
8601
+ return { ...typed,
8602
+ ...computed
8603
+ };
8604
+ }
8605
+ /** The sums of the columns marked `total: "sum"`, as decimals by key. */
8606
+
8607
+ function rowTotals(rows, columns) {
8608
+ const totals = {};
8609
+
8610
+ for (const column of columns) {
8611
+ if (column.total !== 'sum' || !NUMERIC.has(column.propertyType)) continue;
8612
+ let sum = {
8613
+ units: 0n,
8614
+ scale: 0
8615
+ };
8616
+
8617
+ for (const row of rows) {
8618
+ const decimal = cellDecimal(column, row[column.key]);
8619
+ if (decimal) sum = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_0__.add)(sum, decimal);
8620
+ }
8621
+
8622
+ totals[column.key] = sum;
8623
+ }
8624
+
8625
+ return totals;
8626
+ }
8627
+
8628
+ /***/ },
8629
+
8630
+ /***/ "db94c32f22be"
8631
+ (module, __webpack_exports__, __webpack_require__) {
8632
+
8633
+ __webpack_require__.a(module, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {
8634
+ __webpack_require__.r(__webpack_exports__);
8635
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
8636
+ /* harmony export */ SET_FIELD_TYPES: () => (/* binding */ SET_FIELD_TYPES),
8637
+ /* harmony export */ drawsSetField: () => (/* binding */ drawsSetField),
8638
+ /* harmony export */ renderSetField: () => (/* binding */ renderSetField),
8639
+ /* harmony export */ setFieldText: () => (/* binding */ setFieldText)
8640
+ /* harmony export */ });
8641
+ /* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("2a080a730149");
8642
+ /* harmony import */ var _set_fields_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("f59c8bcdc90a");
8643
+ /* harmony import */ var _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("e5483002f3ea");
8644
+ /* harmony import */ var _core_js_page_language__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("43090d1c8307");
8645
+ /* harmony import */ var _decimal_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("f44b979883f0");
8646
+ /* harmony import */ var _money_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("d69ebe7e288e");
8647
+ /* harmony import */ var _rows_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("ebc72103d8b6");
8648
+ /* harmony import */ var _requisites_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("06dfc7b3b9d9");
8649
+ var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([lit__WEBPACK_IMPORTED_MODULE_0__, _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__, _core_js_page_language__WEBPACK_IMPORTED_MODULE_3__]);
8650
+ ([lit__WEBPACK_IMPORTED_MODULE_0__, _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__, _core_js_page_language__WEBPACK_IMPORTED_MODULE_3__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
8651
+ /* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(lit__WEBPACK_IMPORTED_MODULE_0__);
8652
+ /* harmony import */ var _core_js_page_language__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__);
8653
+
8654
+
8655
+
8656
+
8657
+
8658
+
8659
+
8660
+ // The property types the set draws itself, beside the SIMAI Framework field
8661
+ // renderers it draws every other type with (Larena addendum of 2026-11-03 to
8662
+ // the general components task, msg-bf1ad4f3ae00420bb752; Larena property types
8663
+ // standard, notes of 2026-11-03):
8664
+ //
8665
+ // money {amount, currency}: an amount and its ISO 4217 currency
8666
+ // percent a decimal with a % after it
8667
+ // items rows over the field's columns: a table editor, a card a row on a phone
8668
+ // compound a fixed set of parts with one value object, checked together
8669
+ // ru.requisites the compound of a Russian organisation's or person's requisites
8670
+ //
8671
+ // Each is drawn from Framework controls (sf-input with `text-end`, sf-dropdown,
8672
+ // sf-button-icon, sf-button) and, inside a row or a compound, by the Framework
8673
+ // renderers for the types they already draw. Every number is a decimal string
8674
+ // (./decimal.js): nothing here writes a float.
8675
+ //
8676
+ // A control writes what was typed. An entry that is not a value yet -- text
8677
+ // that is not a number, more digits after the point than the currency has, a
8678
+ // ИНН whose control digit is wrong -- is written as typed and reported through
8679
+ // setFieldError, which holds both saves while it stands (port 1.16.0, as a
8680
+ // masked string does), and the control says what is wrong under itself once
8681
+ // the person has left it.
8682
+
8683
+ const TEXT = {
8684
+ en: {
8685
+ currency: 'Currency',
8686
+ notNumber: 'Enter a number',
8687
+ fractionMax: 'At most {n} digits after the point',
8688
+ fractionNone: 'A whole amount, no digits after the point',
8689
+ chooseCurrency: 'Choose a currency',
8690
+ range: 'From {min} to {max}',
8691
+ atLeast: 'At least {min}',
8692
+ atMost: 'At most {max}',
8693
+ addRow: 'Add a row',
8694
+ removeRow: 'Remove the row',
8695
+ rowUp: 'Move the row up',
8696
+ rowDown: 'Move the row down',
8697
+ row: 'Row {n}',
8698
+ total: 'Total',
8699
+ cellsWrong: 'Some cells are not filled in correctly',
8700
+ rows: '{n} rows',
8701
+ row1: '1 row',
8702
+ inn: 'INN',
8703
+ kpp: 'KPP',
8704
+ ogrn: 'OGRN',
8705
+ bik: 'BIK',
8706
+ account: 'Account',
8707
+ corr_account: 'Correspondent account',
8708
+ innRequired: 'The INN is required',
8709
+ innLength: '10 digits for an organisation, 12 for a person',
8710
+ innWrong: 'The INN control digits do not match',
8711
+ kppWrong: 'Nine characters: four digits, two digits or letters, three digits',
8712
+ kppPerson: 'A person\'s INN has no KPP',
8713
+ ogrnLength: '13 digits (OGRN) or 15 (OGRNIP)',
8714
+ ogrnWrong: 'The control digit does not match',
8715
+ ogrnOrganization: 'An organisation has a 13-digit OGRN',
8716
+ ogrnPerson: 'A person has a 15-digit OGRNIP',
8717
+ bikWrong: 'Nine digits starting with 04',
8718
+ accountLength: '20 digits',
8719
+ accountKey: 'The account does not match the BIK',
8720
+ corrStart: 'A correspondent account starts with 301'
8721
+ },
8722
+ ru: {
8723
+ currency: 'Валюта',
8724
+ notNumber: 'Введите число',
8725
+ fractionMax: 'Не больше {n} знаков после запятой',
8726
+ fractionNone: 'Целая сумма, без знаков после запятой',
8727
+ chooseCurrency: 'Выберите валюту',
8728
+ range: 'От {min} до {max}',
8729
+ atLeast: 'Не меньше {min}',
8730
+ atMost: 'Не больше {max}',
8731
+ addRow: 'Добавить строку',
8732
+ removeRow: 'Удалить строку',
8733
+ rowUp: 'Поднять строку',
8734
+ rowDown: 'Опустить строку',
8735
+ row: 'Строка {n}',
8736
+ total: 'Итого',
8737
+ cellsWrong: 'Не все ячейки заполнены верно',
8738
+ rows: '{n} строк',
8739
+ row1: '1 строка',
8740
+ inn: 'ИНН',
8741
+ kpp: 'КПП',
8742
+ ogrn: 'ОГРН',
8743
+ bik: 'БИК',
8744
+ account: 'Расчётный счёт',
8745
+ corr_account: 'Корр. счёт',
8746
+ innRequired: 'ИНН обязателен',
8747
+ innLength: '10 цифр у организации, 12 у физлица',
8748
+ innWrong: 'Не сходятся контрольные цифры ИНН',
8749
+ kppWrong: 'Девять знаков: четыре цифры, две цифры или буквы, три цифры',
8750
+ kppPerson: 'У ИНН физлица нет КПП',
8751
+ ogrnLength: '13 цифр (ОГРН) или 15 (ОГРНИП)',
8752
+ ogrnWrong: 'Не сходится контрольная цифра',
8753
+ ogrnOrganization: 'У организации ОГРН из 13 цифр',
8754
+ ogrnPerson: 'У физлица ОГРНИП из 15 цифр',
8755
+ bikWrong: 'Девять цифр, начиная с 04',
8756
+ accountLength: '20 цифр',
8757
+ accountKey: 'Счёт не сходится с БИК',
8758
+ corrStart: 'Корр. счёт начинается с 301'
8759
+ }
8760
+ };
8761
+ const WORDS_OF = 'sf-view-properties';
8762
+
8763
+ function word(node, key, vars = {}) {
8764
+ let text = (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageText)(TEXT, key, node, WORDS_OF);
8765
+
8766
+ for (const [name, value] of Object.entries(vars)) text = text.replaceAll(`{${name}}`, String(value));
8767
+
8768
+ return text;
8769
+ } // ru counts: 1 строка, 2–4 строки, 5+ строк.
8770
+
8771
+
8772
+ function rowsWord(node, count) {
8773
+ const locale = (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageLocale)(node);
8774
+ if (count === 1) return word(node, 'row1');
8775
+
8776
+ if (locale.startsWith('ru')) {
8777
+ const tens = count % 100;
8778
+ const ones = count % 10;
8779
+ if (ones >= 2 && ones <= 4 && (tens < 12 || tens > 14)) return `${count} строки`;
8780
+ }
8781
+
8782
+ return word(node, 'rows', {
8783
+ n: count
8784
+ });
8785
+ }
8786
+
8787
+ const SET_FIELD_TYPES = Object.freeze(['money', 'percent', 'items', 'compound', 'ru.requisites']); // --- Currencies -------------------------------------------------------------
8788
+ // The currencies a money field offers when it does not fix one: the ones a
8789
+ // Russian-language business meets most, and the value's own currency first
8790
+ // when it is none of them. A field that fixes `currency` offers no choice.
8791
+
8792
+ const OFFERED_CURRENCIES = ['RUB', 'USD', 'EUR', 'CNY', 'KZT', 'BYN', 'AED', 'TRY', 'GBP', 'JPY']; // --- What a person is typing -------------------------------------------------
8793
+ // The text in a decimal input while it is being typed. The value written is
8794
+ // canonical («12.5»); drawn back as such it would move the caret under the
8795
+ // person typing «12,50». So the typed text is kept per control and shown while
8796
+ // it still reads as the value, and dropped when the control is left.
8797
+
8798
+ const DRAFTS = new WeakMap();
8799
+
8800
+ const draftsOf = node => {
8801
+ if (!DRAFTS.has(node)) DRAFTS.set(node, new Map());
8802
+ return DRAFTS.get(node);
8803
+ }; // The controls a person has left: a message stands under a control only then,
8804
+ // as a masked string's does.
8805
+
8806
+
8807
+ const LEFT = new WeakMap();
8808
+
8809
+ const leftOf = node => {
8810
+ if (!LEFT.has(node)) LEFT.set(node, new Set());
8811
+ return LEFT.get(node);
8812
+ };
8813
+
8814
+ const redraw = node => node?.requestComponentUpdate?.('changed');
8815
+
8816
+ function shownText(node, path, value, locale) {
8817
+ const draft = draftsOf(node).get(path);
8818
+ const read = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.readDecimal)(value);
8819
+ if (!read.ok) return String(value ?? '');
8820
+
8821
+ if (typeof draft === 'string') {
8822
+ const typed = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.readDecimal)(draft);
8823
+ if (typed.ok && typed.value === read.value) return draft;
8824
+ }
8825
+
8826
+ return (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.editableDecimal)(read.value, locale);
8827
+ } // The mistake of a typed decimal, or null: not a number, more digits after the
8828
+ // point than allowed, outside the bounds.
8829
+
8830
+
8831
+ function decimalError(node, raw, {
8832
+ maxFraction = null,
8833
+ min = null,
8834
+ max = null
8835
+ } = {}) {
8836
+ const read = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.readDecimal)(raw);
8837
+ if (!read.ok) return word(node, 'notNumber');
8838
+ if (read.value === null) return null;
8839
+
8840
+ if (maxFraction !== null && (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.fractionDigits)(read.value) > maxFraction) {
8841
+ return maxFraction === 0 ? word(node, 'fractionNone') : word(node, 'fractionMax', {
8842
+ n: maxFraction
8843
+ });
8844
+ }
8845
+
8846
+ const value = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.toDecimal)(read.value);
8847
+ const low = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.toDecimal)(min);
8848
+ const high = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.toDecimal)(max);
8849
+ const locale = (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageLocale)(node);
8850
+
8851
+ if (low && (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.compare)(value, low) < 0 || high && (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.compare)(value, high) > 0) {
8852
+ if (low && high) return word(node, 'range', {
8853
+ min: (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.formatDecimal)(min, locale),
8854
+ max: (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.formatDecimal)(max, locale)
8855
+ });
8856
+ return low ? word(node, 'atLeast', {
8857
+ min: (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.formatDecimal)(min, locale)
8858
+ }) : word(node, 'atMost', {
8859
+ max: (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.formatDecimal)(max, locale)
8860
+ });
8861
+ }
8862
+
8863
+ return null;
8864
+ }
8865
+ /**
8866
+ * One decimal input: sf-input with the decimal keyboard and `text-end` (a % or
8867
+ * a currency sign). `write(text, error)` gets what was typed -- canonical when
8868
+ * it reads as a number -- and the mistake, or null.
8869
+ */
8870
+
8871
+
8872
+ function decimalInput(node, {
8873
+ path,
8874
+ value,
8875
+ size,
8876
+ label,
8877
+ required,
8878
+ textEnd,
8879
+ placeholder,
8880
+ check,
8881
+ write
8882
+ }) {
8883
+ const locale = (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageLocale)(node);
8884
+ const text = shownText(node, path, value, locale);
8885
+ const error = check(text);
8886
+ const shown = error && leftOf(node).has(path) ? error : '';
8887
+
8888
+ const typed = event => {
8889
+ const raw = event.target?.value ?? '';
8890
+ draftsOf(node).set(path, raw);
8891
+ const read = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.readDecimal)(raw);
8892
+ write(read.ok ? read.value : raw, check(raw));
8893
+ };
8894
+
8895
+ return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
8896
+ <sf-input
8897
+ class="sf-view-fields-decimal"
8898
+ size=${size}
8899
+ appearance="bordered"
8900
+ inputmode="decimal"
8901
+ value=${text}
8902
+ text-end=${textEnd || lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
8903
+ placeholder=${placeholder || lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
8904
+ ?required=${Boolean(required)}
8905
+ ?invalid=${Boolean(shown)}
8906
+ error-message=${shown || lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
8907
+ aria-label=${label || ''}
8908
+ data-path=${path}
8909
+ @input=${typed}
8910
+ @change=${typed}
8911
+ @focusout=${() => {
8912
+ draftsOf(node).delete(path);
8913
+ leftOf(node).add(path);
8914
+ redraw(node);
8915
+ }}
8916
+ ></sf-input>
8917
+ `;
8918
+ } // --- percent -------------------------------------------------------------------
8919
+
8920
+
8921
+ function percentBounds(field) {
8922
+ // 0 and 100 when the field sets none (property types standard §2).
8923
+ return {
8924
+ min: field.min ?? '0',
8925
+ max: field.max ?? '100'
8926
+ };
8927
+ }
8928
+
8929
+ function renderPercentEdit(field, value, host, ctx) {
8930
+ const {
8931
+ min,
8932
+ max
8933
+ } = percentBounds(field);
8934
+ return decimalInput(ctx.node, {
8935
+ path: ctx.path ?? String(field.key ?? ''),
8936
+ value,
8937
+ size: ctx.size,
8938
+ label: field.label || field.key,
8939
+ required: field.required,
8940
+ textEnd: '%',
8941
+ placeholder: field.placeholder,
8942
+ check: text => decimalError(ctx.node, text, {
8943
+ min,
8944
+ max
8945
+ }),
8946
+ write: (next, error) => {
8947
+ host.setFieldValue(field, next);
8948
+ host.setFieldError?.(field, error);
8949
+ }
8950
+ });
8951
+ }
8952
+
8953
+ function renderPercentView(field, value, ctx) {
8954
+ const text = (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.percentText)(value, (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageLocale)(ctx.node));
8955
+ return text ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-field-view">${text}</span>` : lit__WEBPACK_IMPORTED_MODULE_0__.nothing;
8956
+ } // --- money ---------------------------------------------------------------------
8957
+
8958
+
8959
+ function renderMoneyEdit(field, value, host, ctx) {
8960
+ const node = ctx.node;
8961
+ const locale = (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageLocale)(node);
8962
+ const path = ctx.path ?? String(field.key ?? '');
8963
+ const fixed = typeof field.currency === 'string' && field.currency ? field.currency : null;
8964
+ const parts = (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.moneyParts)(value, fixed); // A currency chosen before an amount is typed waits here: a value is an
8965
+ // amount and its currency, never a currency alone.
8966
+
8967
+ const currencyPath = `${path}#currency`;
8968
+ const currency = parts.currency || draftsOf(node).get(currencyPath) || null;
8969
+ const minor = currency ? (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.currencyOf)(currency, locale).minor : null;
8970
+
8971
+ const check = text => {
8972
+ const error = decimalError(node, text, {
8973
+ maxFraction: minor,
8974
+ min: field.min ?? null,
8975
+ max: field.max ?? null
8976
+ });
8977
+ if (error) return error;
8978
+ return (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.readDecimal)(text).value !== null && !currency ? word(node, 'chooseCurrency') : null;
8979
+ };
8980
+
8981
+ const write = (amount, error, code = currency) => {
8982
+ host.setFieldValue(field, amount === null ? null : {
8983
+ amount,
8984
+ currency: code
8985
+ });
8986
+ host.setFieldError?.(field, error);
8987
+ };
8988
+
8989
+ const amount = decimalInput(node, {
8990
+ path,
8991
+ value: parts.amount,
8992
+ size: ctx.size,
8993
+ label: field.label || field.key,
8994
+ required: field.required,
8995
+ textEnd: fixed ? (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.currencyOf)(fixed, locale).sign : '',
8996
+ placeholder: field.placeholder,
8997
+ check,
8998
+ write
8999
+ });
9000
+ if (fixed) return amount;
9001
+ const offered = [...new Set([...(currency ? [currency] : []), ...OFFERED_CURRENCIES])];
9002
+ return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9003
+ <span class="sf-view-fields-money flex gap-1/3 min-w-0">
9004
+ ${amount}
9005
+ <sf-dropdown
9006
+ class="sf-view-fields-currency"
9007
+ size=${ctx.size}
9008
+ appearance="outlined"
9009
+ mode="select"
9010
+ search="false"
9011
+ value=${currency ?? ''}
9012
+ placeholder=${word(node, 'currency')}
9013
+ aria-label=${word(node, 'currency')}
9014
+ .options=${offered.map(code => ({
9015
+ type: 'text',
9016
+ size: '1',
9017
+ value: code,
9018
+ text: `${code} ${(0,_money_js__WEBPACK_IMPORTED_MODULE_5__.currencyOf)(code, locale).sign === code ? '' : (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.currencyOf)(code, locale).sign}`.trim(),
9019
+ selected: code === currency
9020
+ }))}
9021
+ @change=${event => {
9022
+ const code = event.detail?.value || null;
9023
+ draftsOf(node).set(currencyPath, code);
9024
+ const typed = parts.amount;
9025
+
9026
+ if (typed !== null && typed !== '') {
9027
+ const nextMinor = code ? (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.currencyOf)(code, locale).minor : null;
9028
+ const error = decimalError(node, typed, {
9029
+ maxFraction: nextMinor,
9030
+ min: field.min ?? null,
9031
+ max: field.max ?? null
9032
+ }) || (code ? null : word(node, 'chooseCurrency'));
9033
+ write((0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.readDecimal)(typed).ok ? (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.readDecimal)(typed).value : typed, error, code);
9034
+ } else {
9035
+ redraw(node);
9036
+ }
9037
+ }}
9038
+ ></sf-dropdown>
9039
+ </span>
9040
+ `;
9041
+ }
9042
+
9043
+ function moneyText(field, value, locale) {
9044
+ const fixed = typeof field.currency === 'string' && field.currency ? field.currency : null;
9045
+ const {
9046
+ amount,
9047
+ currency
9048
+ } = (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.moneyParts)(value, fixed);
9049
+ return amount === null ? '' : (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.formatMoney)(amount, currency, locale);
9050
+ }
9051
+
9052
+ function renderMoneyView(field, value, ctx) {
9053
+ const text = moneyText(field, value, (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageLocale)(ctx.node));
9054
+ return text ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-field-view sf-view-fields-amount">${text}</span>` : lit__WEBPACK_IMPORTED_MODULE_0__.nothing;
9055
+ } // --- number inside a row -----------------------------------------------------------
9056
+ // A number cell of a row is a decimal string as a money amount is: the
9057
+ // Framework's number editor writes a float, which the rows refuse. An integer
9058
+ // cell is the Framework's own.
9059
+
9060
+
9061
+ function renderDecimalEdit(field, value, host, ctx) {
9062
+ return decimalInput(ctx.node, {
9063
+ path: ctx.path ?? String(field.key ?? ''),
9064
+ value,
9065
+ size: ctx.size,
9066
+ label: field.label || field.key,
9067
+ required: field.required,
9068
+ textEnd: field.unit || '',
9069
+ placeholder: field.placeholder,
9070
+ check: text => decimalError(ctx.node, text, {
9071
+ min: field.min ?? null,
9072
+ max: field.max ?? null
9073
+ }),
9074
+ write: (next, error) => {
9075
+ host.setFieldValue(field, next);
9076
+ host.setFieldError?.(field, error);
9077
+ }
9078
+ });
9079
+ }
9080
+
9081
+ function decimalText(field, value, locale) {
9082
+ const text = (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.formatDecimal)(value, locale);
9083
+ return text && field.unit ? `${text} ${field.unit}` : text;
9084
+ } // --- items: rows over columns ------------------------------------------------------
9085
+
9086
+
9087
+ function cellText(column, cell, columns, locale, viewHost) {
9088
+ if (cell === null || typeof cell === 'undefined' || cell === '') return null;
9089
+
9090
+ switch (column.propertyType) {
9091
+ case 'money':
9092
+ {
9093
+ const {
9094
+ amount,
9095
+ currency
9096
+ } = (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.moneyParts)(cell, (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.columnCurrency)(column, columns));
9097
+ return amount === null ? null : (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.formatMoney)(amount, currency, locale);
9098
+ }
9099
+
9100
+ case 'percent':
9101
+ return (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.percentText)(cell, locale);
9102
+
9103
+ case 'number':
9104
+ return decimalText(column, cell, locale);
9105
+
9106
+ default:
9107
+ {
9108
+ const shown = (0,_field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__.renderViewField)({ ...column,
9109
+ value: cell
9110
+ }, cell, viewHost, {
9111
+ size: '1'
9112
+ });
9113
+ return shown === null || shown === lit__WEBPACK_IMPORTED_MODULE_0__.nothing ? null : shown;
9114
+ }
9115
+ }
9116
+ }
9117
+
9118
+ function totalText(column, total, columns, locale) {
9119
+ if (column.propertyType === 'money') {
9120
+ const currency = (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.columnCurrency)(column, columns);
9121
+ return (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.formatMoney)((0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.decimalString)(total), currency, locale);
9122
+ }
9123
+
9124
+ if (column.propertyType === 'percent') return (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.percentText)((0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.decimalString)(total), locale);
9125
+ return decimalText(column, (0,_decimal_js__WEBPACK_IMPORTED_MODULE_4__.decimalString)(total), locale);
9126
+ } // A column's share of the row: text widest, a yes-or-no narrowest.
9127
+
9128
+
9129
+ function track(column) {
9130
+ switch (column.propertyType) {
9131
+ case 'boolean':
9132
+ return 'minmax(4rem, auto)';
9133
+ // Wide enough for the control's own padding, a suffix (% or a currency
9134
+ // sign) and the digits a person types: a 5.5rem percent showed «2 %» for 20.
9135
+
9136
+ case 'integer':
9137
+ return 'minmax(5.5rem, 0.6fr)';
9138
+
9139
+ case 'percent':
9140
+ return 'minmax(6.5rem, 0.6fr)';
9141
+
9142
+ case 'number':
9143
+ return 'minmax(6.5rem, 0.7fr)';
9144
+
9145
+ case 'money':
9146
+ return column.currency ? 'minmax(9rem, 0.9fr)' : 'minmax(13rem, 1.2fr)';
9147
+
9148
+ case 'date':
9149
+ return 'minmax(9rem, 0.8fr)';
9150
+
9151
+ case 'choice':
9152
+ return 'minmax(8rem, 1fr)';
9153
+
9154
+ default:
9155
+ return 'minmax(10rem, 2fr)';
9156
+ }
9157
+ }
9158
+
9159
+ function itemsSummary(field, rows, columns, ctx) {
9160
+ const locale = (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageLocale)(ctx.node);
9161
+ const totals = (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.rowTotals)(rows, columns);
9162
+ const first = columns.find(column => Object.hasOwn(totals, column.key) && column.propertyType === 'money') ?? columns.find(column => Object.hasOwn(totals, column.key));
9163
+ const count = rowsWord(ctx.node, rows.length);
9164
+ return first ? `${count}, ${word(ctx.node, 'total').toLowerCase()} ${totalText(first, totals[first.key], columns, locale)}` : count;
9165
+ }
9166
+
9167
+ function renderItemsTable(field, rows, columns, ctx, {
9168
+ editing,
9169
+ host
9170
+ }) {
9171
+ const node = ctx.node;
9172
+ const locale = (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageLocale)(node);
9173
+ const key = String(field.key ?? '');
9174
+ const minRows = Number.isInteger(field.minRows) ? field.minRows : 0;
9175
+ const maxRows = Number.isInteger(field.maxRows) ? field.maxRows : 1000; // Fewer rows than the field asks for are drawn as empty rows to fill in,
9176
+ // and written only once something is typed in them.
9177
+
9178
+ const drawn = editing ? [...rows, ...Array.from({
9179
+ length: Math.max(0, minRows - rows.length)
9180
+ }, () => ({}))] : rows;
9181
+ const totals = (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.rowTotals)(rows, columns);
9182
+ const hasTotals = Object.keys(totals).length > 0;
9183
+ const template = `${columns.map(track).join(' ')}${editing ? ' auto' : ''}`; // Every cell's mistake, by row and column, reported as one for the field:
9184
+ // the field holds the save while any cell does.
9185
+
9186
+ const errors = cellErrorsOf(node, key);
9187
+
9188
+ const reportCells = () => {
9189
+ const any = [...errors.values()].some(Boolean);
9190
+ host.setFieldError?.(field, any ? word(node, 'cellsWrong') : null);
9191
+ };
9192
+
9193
+ const writeRows = next => {
9194
+ const computed = next.map(row => (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.computeRow)(row, columns, locale));
9195
+ host.setFieldValue(field, computed.length ? computed : null);
9196
+ };
9197
+
9198
+ const writeCell = (index, column, cell) => {
9199
+ const next = drawn.map(row => ({ ...row
9200
+ }));
9201
+ if (cell === null || typeof cell === 'undefined' || cell === '') delete next[index][column.key];else next[index][column.key] = cell;
9202
+ writeRows(next.slice(0, Math.max(rows.length, index + 1)));
9203
+ }; // Rows move: what was typed in a cell and is not a value yet goes with the
9204
+ // cell's place, so the drafts of this field are dropped.
9205
+
9206
+
9207
+ const reshape = next => {
9208
+ for (const path of [...draftsOf(node).keys()]) if (path.startsWith(`${key}[`)) draftsOf(node).delete(path);
9209
+
9210
+ for (const path of [...leftOf(node)]) if (path.startsWith(`${key}[`)) leftOf(node).delete(path);
9211
+
9212
+ errors.clear();
9213
+ reportCells();
9214
+ writeRows(next);
9215
+ };
9216
+
9217
+ const cell = (row, index, column) => {
9218
+ const path = `${key}[${index}].${column.key}`;
9219
+ const value = row[column.key];
9220
+
9221
+ if (!editing || column.compute || field.readonly === true || column.readonly === true) {
9222
+ const text = cellText(column, column.compute && editing ? (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.computeRow)(row, columns, locale)[column.key] : value, columns, locale, ctx.viewHost);
9223
+ return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-view-items-text ${column.compute ? 'color-on-surface-variant' : ''}" data-computed=${column.compute ? 'true' : lit__WEBPACK_IMPORTED_MODULE_0__.nothing}>${text ?? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="color-on-surface-variant">—</span>`}</span>`;
9224
+ }
9225
+
9226
+ const cellField = { ...column,
9227
+ key: path,
9228
+ label: column.label || column.key,
9229
+ value
9230
+ };
9231
+ const cellHost = {
9232
+ setFieldValue: (_target, next) => writeCell(index, column, next),
9233
+ setFieldError: (_target, message) => {
9234
+ errors.set(path, message || null);
9235
+ reportCells();
9236
+ }
9237
+ };
9238
+ const cellCtx = { ...ctx,
9239
+ path
9240
+ };
9241
+
9242
+ switch (column.propertyType) {
9243
+ case 'money':
9244
+ return renderMoneyEdit({ ...cellField,
9245
+ currency: column.currency
9246
+ }, value, cellHost, cellCtx);
9247
+
9248
+ case 'percent':
9249
+ return renderPercentEdit(cellField, value, cellHost, cellCtx);
9250
+
9251
+ case 'number':
9252
+ return renderDecimalEdit(cellField, value, cellHost, cellCtx);
9253
+
9254
+ default:
9255
+ {
9256
+ const control = (0,_field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__.renderEditField)(cellField, value, cellHost, {
9257
+ size: ctx.size
9258
+ });
9259
+ return control ?? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-view-items-text">${cellText(column, value, columns, locale, ctx.viewHost) ?? '—'}</span>`;
9260
+ }
9261
+ }
9262
+ };
9263
+
9264
+ const rowActions = index => (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9265
+ <span class="sf-view-items-actions flex items-cross-center gap-1/4" role="cell">
9266
+ <sf-button-icon size="1/2" appearance="link" scheme="secondary" icon="keyboard_arrow_up"
9267
+ data-action="row-up" ?disabled=${index === 0 || index >= rows.length}
9268
+ title=${word(node, 'rowUp')} aria-label=${word(node, 'rowUp')}
9269
+ @click=${() => {
9270
+ const next = rows.slice();
9271
+ [next[index - 1], next[index]] = [next[index], next[index - 1]];
9272
+ reshape(next);
9273
+ }}></sf-button-icon>
9274
+ <sf-button-icon size="1/2" appearance="link" scheme="secondary" icon="keyboard_arrow_down"
9275
+ data-action="row-down" ?disabled=${index >= rows.length - 1}
9276
+ title=${word(node, 'rowDown')} aria-label=${word(node, 'rowDown')}
9277
+ @click=${() => {
9278
+ const next = rows.slice();
9279
+ [next[index + 1], next[index]] = [next[index], next[index + 1]];
9280
+ reshape(next);
9281
+ }}></sf-button-icon>
9282
+ <sf-button-icon size="1/2" appearance="link" scheme="secondary" icon="delete"
9283
+ data-action="row-remove" ?disabled=${drawn.length <= minRows || index >= rows.length}
9284
+ title=${word(node, 'removeRow')} aria-label=${word(node, 'removeRow')}
9285
+ @click=${() => reshape(rows.filter((_row, at) => at !== index))}></sf-button-icon>
9286
+ </span>
9287
+ `;
9288
+
9289
+ return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9290
+ <span class="sf-view-items-box">
9291
+ <span class="sf-view-items ${editing ? 'sf-view-items--edit' : ''}" data-items=${key} role="table"
9292
+ aria-label=${field.label || key} style=${`--sf-view-items-columns: ${template}`}>
9293
+ <span class="sf-view-items-head" role="row">
9294
+ ${columns.map(column => (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-view-items-heading ${_rows_js__WEBPACK_IMPORTED_MODULE_6__.NUMERIC.has(column.propertyType) ? 'sf-view-items-numeric' : ''}" role="columnheader">${column.label || column.key}${editing && column.required && !column.compute ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="color-error" aria-hidden="true"> *</span>` : lit__WEBPACK_IMPORTED_MODULE_0__.nothing}</span>`)}
9295
+ ${editing ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-view-items-heading" role="columnheader"></span>` : lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
9296
+ </span>
9297
+ ${drawn.map((row, index) => (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9298
+ <span class="sf-view-items-row" role="row" data-row=${index} aria-label=${word(node, 'row', {
9299
+ n: index + 1
9300
+ })}>
9301
+ ${columns.map(column => (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9302
+ <span class="sf-view-items-cell ${_rows_js__WEBPACK_IMPORTED_MODULE_6__.NUMERIC.has(column.propertyType) ? 'sf-view-items-numeric' : ''}" role="cell" data-column=${column.key}>
9303
+ <span class="sf-view-items-cell-label color-on-surface-variant" aria-hidden="true">${column.label || column.key}</span>
9304
+ ${cell(row, index, column)}
9305
+ </span>`)}
9306
+ ${editing ? rowActions(index) : lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
9307
+ </span>`)}
9308
+ ${hasTotals && rows.length ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9309
+ <span class="sf-view-items-row sf-view-items-totals" role="row" data-totals="true">
9310
+ ${columns.map((column, at) => (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9311
+ <span class="sf-view-items-cell ${_rows_js__WEBPACK_IMPORTED_MODULE_6__.NUMERIC.has(column.propertyType) ? 'sf-view-items-numeric' : ''} ${Object.hasOwn(totals, column.key) ? '' : 'sf-view-items-cell--blank'}" role="cell" data-column=${column.key}>
9312
+ ${Object.hasOwn(totals, column.key) ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-view-items-cell-label color-on-surface-variant" aria-hidden="true">${word(node, 'total')}: ${column.label || column.key}</span><span class="sf-view-items-text sf-view-items-total">${totalText(column, totals[column.key], columns, locale)}</span>` : at === 0 ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-view-items-text sf-view-items-total-word">${word(node, 'total')}</span>` : lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
9313
+ </span>`)}
9314
+ ${editing ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span role="cell"></span>` : lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
9315
+ </span>` : lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
9316
+ ${editing ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9317
+ <span class="sf-view-items-foot flex items-cross-center gap-1">
9318
+ <sf-button appearance="outline" size=${ctx.size} icon="add" text=${word(node, 'addRow')}
9319
+ data-action="row-add" ?disabled=${drawn.length >= maxRows}
9320
+ @click=${() => reshape([...drawn, {}])}></sf-button>
9321
+ </span>` : lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
9322
+ </span>
9323
+ </span>
9324
+ `;
9325
+ }
9326
+
9327
+ const CELL_ERRORS = new WeakMap();
9328
+
9329
+ function cellErrorsOf(node, key) {
9330
+ if (!CELL_ERRORS.has(node)) CELL_ERRORS.set(node, new Map());
9331
+ const all = CELL_ERRORS.get(node);
9332
+ if (!all.has(key)) all.set(key, new Map());
9333
+ return all.get(key);
9334
+ }
9335
+
9336
+ function renderItemsEdit(field, value, host, ctx) {
9337
+ return renderItemsTable(field, (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.rowsOf)(value), (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.columnsOf)(field), ctx, {
9338
+ editing: true,
9339
+ host
9340
+ });
9341
+ }
9342
+
9343
+ function renderItemsView(field, value, ctx) {
9344
+ const rows = (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.rowsOf)(value);
9345
+ if (!rows.length) return lit__WEBPACK_IMPORTED_MODULE_0__.nothing;
9346
+ if (ctx.summary) return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-field-view">${itemsSummary(field, rows, (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.columnsOf)(field), ctx)}</span>`;
9347
+ return renderItemsTable(field, rows, (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.columnsOf)(field), ctx, {
9348
+ editing: false,
9349
+ host: null
9350
+ });
9351
+ } // --- compound: a fixed set of parts, one value --------------------------------------
9352
+ // The parts of a requisites field, in the standard's order, of those the field
9353
+ // names (`parts`; all six when it names none). Each is typed as digits, the КПП
9354
+ // as digits and capital letters.
9355
+
9356
+
9357
+ const REQUISITE_LENGTH = {
9358
+ inn: 12,
9359
+ kpp: 9,
9360
+ ogrn: 15,
9361
+ bik: 9,
9362
+ account: 20,
9363
+ corr_account: 20
9364
+ };
9365
+
9366
+ function requisiteParts(field) {
9367
+ const named = Array.isArray(field.parts) ? field.parts.map(String) : _requisites_js__WEBPACK_IMPORTED_MODULE_7__.REQUISITE_PARTS;
9368
+ return _requisites_js__WEBPACK_IMPORTED_MODULE_7__.REQUISITE_PARTS.filter(part => named.includes(part));
9369
+ }
9370
+
9371
+ function compoundParts(field) {
9372
+ return (Array.isArray(field.parts) ? field.parts : []).map(part => part && typeof part === 'object' ? { ...part,
9373
+ propertyType: part.propertyType || part.type
9374
+ } : null).filter(part => part?.key);
9375
+ }
9376
+
9377
+ function objectOf(value) {
9378
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
9379
+ } // The value written: the parts in their order, an empty part no key, and
9380
+ // nothing at all when every part is empty.
9381
+
9382
+
9383
+ function compoundValue(order, value) {
9384
+ const next = {};
9385
+
9386
+ for (const part of order) {
9387
+ const one = value[part];
9388
+ if (one !== null && typeof one !== 'undefined' && one !== '') next[part] = one;
9389
+ }
9390
+
9391
+ return Object.keys(next).length ? next : null;
9392
+ }
9393
+
9394
+ function renderRequisitesEdit(field, value, host, ctx) {
9395
+ const node = ctx.node;
9396
+ const key = String(field.key ?? '');
9397
+ const parts = requisiteParts(field);
9398
+ const held = objectOf(value);
9399
+ const errors = (0,_requisites_js__WEBPACK_IMPORTED_MODULE_7__.requisiteErrors)(held, parts);
9400
+
9401
+ const write = (part, text) => {
9402
+ const cleaned = part === 'kpp' ? text.replace(/\s/gu, '').toUpperCase() : text.replace(/\D/gu, '');
9403
+ const next = compoundValue(parts, { ...held,
9404
+ [part]: cleaned
9405
+ });
9406
+ const mistakes = (0,_requisites_js__WEBPACK_IMPORTED_MODULE_7__.requisiteErrors)(next ?? {}, parts); // Nothing typed in a field that is not required is no mistake.
9407
+
9408
+ const blank = next === null && field.required !== true;
9409
+ host.setFieldValue(field, next);
9410
+ host.setFieldError?.(field, !blank && Object.keys(mistakes).length ? word(node, mistakes[Object.keys(mistakes)[0]]) : null);
9411
+ };
9412
+
9413
+ return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9414
+ <span class="sf-view-fields-compound grid gap-1 w-full min-w-0" data-compound=${key}>
9415
+ ${parts.map(part => {
9416
+ const path = `${key}.${part}`;
9417
+ const left = leftOf(node).has(path);
9418
+ const blank = Object.keys(held).length === 0 && field.required !== true;
9419
+ const message = left && !blank && errors[part] ? word(node, errors[part]) : '';
9420
+ return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9421
+ <span class="sf-view-fields-part flex flex-col gap-1/4 min-w-0 ${part === 'account' || part === 'corr_account' ? 'sf-view-fields-part--wide' : ''}" data-part=${part}>
9422
+ <span class="sf-view-fields-part-label color-on-surface-variant">${word(node, part)}${part === 'inn' && field.required ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="color-error" aria-hidden="true"> *</span>` : lit__WEBPACK_IMPORTED_MODULE_0__.nothing}</span>
9423
+ <sf-input
9424
+ size=${ctx.size}
9425
+ appearance="bordered"
9426
+ inputmode=${part === 'kpp' ? 'text' : 'numeric'}
9427
+ maxlength=${String(REQUISITE_LENGTH[part])}
9428
+ value=${String(held[part] ?? '')}
9429
+ ?required=${part === 'inn' && field.required === true}
9430
+ ?invalid=${Boolean(message)}
9431
+ error-message=${message || lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
9432
+ aria-label=${`${field.label || key}: ${word(node, part)}`}
9433
+ @input=${event => write(part, String(event.target?.value ?? ''))}
9434
+ @change=${event => write(part, String(event.target?.value ?? ''))}
9435
+ @focusout=${() => {
9436
+ leftOf(node).add(path);
9437
+ redraw(node);
9438
+ }}
9439
+ ></sf-input>
9440
+ </span>`;
9441
+ })}
9442
+ </span>
9443
+ `;
9444
+ }
9445
+
9446
+ function requisitesText(field, value, node) {
9447
+ const held = objectOf(value);
9448
+ return requisiteParts(field).filter(part => held[part]).map(part => `${word(node, part)} ${held[part]}`).join(', ');
9449
+ }
9450
+
9451
+ function renderRequisitesView(field, value, ctx) {
9452
+ const text = requisitesText(field, value, ctx.node);
9453
+ return text ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-field-view">${text}</span>` : lit__WEBPACK_IMPORTED_MODULE_0__.nothing;
9454
+ }
9455
+
9456
+ function renderCompoundEdit(field, value, host, ctx) {
9457
+ const node = ctx.node;
9458
+ const key = String(field.key ?? '');
9459
+ const parts = compoundParts(field);
9460
+ const order = parts.map(part => part.key);
9461
+ const held = objectOf(value);
9462
+ const errors = cellErrorsOf(node, key);
9463
+ return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9464
+ <span class="sf-view-fields-compound grid gap-1 w-full min-w-0" data-compound=${key}>
9465
+ ${parts.map(part => {
9466
+ const path = `${key}.${part.key}`;
9467
+ const partField = { ...part,
9468
+ key: path,
9469
+ label: part.label || part.key,
9470
+ readonly: field.readonly === true || part.readonly === true
9471
+ };
9472
+ const partHost = {
9473
+ setFieldValue: (_target, next) => host.setFieldValue(field, compoundValue(order, { ...held,
9474
+ [part.key]: next
9475
+ })),
9476
+ setFieldError: (_target, message) => {
9477
+ errors.set(path, message || null);
9478
+ const first = [...errors.values()].find(Boolean);
9479
+ host.setFieldError?.(field, first ?? null);
9480
+ }
9481
+ };
9482
+ const partCtx = { ...ctx,
9483
+ path
9484
+ };
9485
+ const control = SET_CONTROLS[part.propertyType]?.edit(partField, held[part.key], partHost, partCtx) ?? (0,_field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__.renderEditField)(partField, held[part.key], partHost, {
9486
+ size: ctx.size
9487
+ });
9488
+ return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`
9489
+ <span class="sf-view-fields-part flex flex-col gap-1/4 min-w-0 ${part.width === 'full' ? 'sf-view-fields-part--wide' : ''}" data-part=${part.key}>
9490
+ <span class="sf-view-fields-part-label color-on-surface-variant">${partField.label}${part.required ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="color-error" aria-hidden="true"> *</span>` : lit__WEBPACK_IMPORTED_MODULE_0__.nothing}</span>
9491
+ ${control ?? lit__WEBPACK_IMPORTED_MODULE_0__.nothing}
9492
+ </span>`;
9493
+ })}
9494
+ </span>
9495
+ `;
9496
+ }
9497
+
9498
+ function renderCompoundView(field, value, ctx) {
9499
+ const held = objectOf(value);
9500
+ const shown = compoundParts(field).filter(part => held[part.key] !== null && typeof held[part.key] !== 'undefined' && held[part.key] !== '');
9501
+ if (!shown.length) return lit__WEBPACK_IMPORTED_MODULE_0__.nothing;
9502
+ return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-field-view sf-view-fields-compound-view">${shown.map((part, at) => {
9503
+ const own = SET_CONTROLS[part.propertyType]?.view({ ...part
9504
+ }, held[part.key], ctx);
9505
+ const content = own ?? (0,_field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__.renderViewField)({ ...part
9506
+ }, held[part.key], ctx.viewHost, {
9507
+ size: ctx.size
9508
+ }) ?? String(held[part.key]);
9509
+ return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`${at ? ', ' : ''}<span class="color-on-surface-variant">${part.label || part.key}</span> ${content}`;
9510
+ })}</span>`;
9511
+ } // --- the map ---------------------------------------------------------------------
9512
+
9513
+
9514
+ const SET_CONTROLS = {
9515
+ money: {
9516
+ edit: renderMoneyEdit,
9517
+ view: renderMoneyView
9518
+ },
9519
+ percent: {
9520
+ edit: renderPercentEdit,
9521
+ view: renderPercentView
9522
+ },
9523
+ items: {
9524
+ edit: renderItemsEdit,
9525
+ view: renderItemsView
9526
+ },
9527
+ compound: {
9528
+ edit: renderCompoundEdit,
9529
+ view: renderCompoundView
9530
+ },
9531
+ 'ru.requisites': {
9532
+ edit: renderRequisitesEdit,
9533
+ view: renderRequisitesView
9534
+ }
9535
+ };
9536
+ /** Whether the set draws this property type itself. */
9537
+
9538
+ function drawsSetField(field) {
9539
+ return Object.hasOwn(SET_CONTROLS, String(field?.propertyType || field?.type || ''));
9540
+ }
9541
+ /**
9542
+ * A field of a type the set draws, edited or shown. `ctx` is {node, size,
9543
+ * viewHost, disabled}: the element whose page language the words follow, the
9544
+ * size on the ladder, the host's formatFieldValue, and whether a condition
9545
+ * turns the field off. A field the person may not change is shown, as the
9546
+ * Framework renderers show one.
9547
+ */
9548
+
9549
+ function renderSetField(field, value, editing, host, ctx) {
9550
+ const control = SET_CONTROLS[String(field.propertyType || field.type)];
9551
+ if (!control) return null;
9552
+ const formatted = !editing ? ctx.viewHost?.formatFieldValue?.(field, value) : null;
9553
+ if (typeof formatted === 'string' && formatted !== '') return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html)`<span class="sf-field-view">${formatted}</span>`;
9554
+
9555
+ if (editing && field.readonly !== true && ctx.disabled !== true && host?.setFieldValue) {
9556
+ return control.edit(field, value, host, ctx);
9557
+ }
9558
+
9559
+ return control.view(field, value, ctx);
9560
+ }
9561
+ /** A field's value as one line of text: «1 500,50 ₽», «2 строки, итого 2 499,99 ₽». */
9562
+
9563
+ function setFieldText(field, value, node) {
9564
+ const locale = (0,_core_js_page_language__WEBPACK_IMPORTED_MODULE_3__.pageLocale)(node);
9565
+
9566
+ switch (String(field?.propertyType || field?.type || '')) {
9567
+ case 'money':
9568
+ return moneyText(field, value, locale);
9569
+
9570
+ case 'percent':
9571
+ return (0,_money_js__WEBPACK_IMPORTED_MODULE_5__.percentText)(value, locale);
9572
+
9573
+ case 'items':
9574
+ {
9575
+ const rows = (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.rowsOf)(value);
9576
+ return rows.length ? itemsSummary(field, rows, (0,_rows_js__WEBPACK_IMPORTED_MODULE_6__.columnsOf)(field), {
9577
+ node
9578
+ }) : '';
9579
+ }
9580
+
9581
+ case 'ru.requisites':
9582
+ return requisitesText(field, value, node);
9583
+
9584
+ default:
9585
+ return null;
9586
+ }
9587
+ }
9588
+ __webpack_async_result__();
9589
+ } catch(e) { __webpack_async_result__(e); } });
9590
+
9591
+ /***/ },
9592
+
9593
+ /***/ "40b137e60526"
9594
+ (module, __webpack_exports__, __webpack_require__) {
9595
+
9596
+ __webpack_require__.a(module, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {
9597
+ __webpack_require__.r(__webpack_exports__);
9598
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
9599
+ /* harmony export */ renderPropertyViewTemplate: () => (/* binding */ renderPropertyViewTemplate)
9600
+ /* harmony export */ });
9601
+ /* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("2a080a730149");
9602
+ /* harmony import */ var _default_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("9e9dad7bcc09");
9603
+ /* harmony import */ var _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("e5483002f3ea");
9604
+ /* harmony import */ var _field_value_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("62c5c417c97d");
9605
+ var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([lit__WEBPACK_IMPORTED_MODULE_0__, _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__, _field_value_js__WEBPACK_IMPORTED_MODULE_3__]);
9606
+ ([lit__WEBPACK_IMPORTED_MODULE_0__, _field_renderers_index_js__WEBPACK_IMPORTED_MODULE_2__, _field_value_js__WEBPACK_IMPORTED_MODULE_3__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
9607
+ /* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(lit__WEBPACK_IMPORTED_MODULE_0__);
9608
+
9609
+
9610
+
9611
+ // The arrangement, drawn in the component's own light DOM. Not in a shadow root:
9612
+ // the field controls are Smart elements whose stylesheets are document-level, and
9613
+ // a document stylesheet does not cross a shadow boundary. sf-view slots its
9614
+ // children for exactly this reason and says so beside the slot; the first version
9615
+ // of this composite built them inside a shadow root and every control came out
9616
+ // with its markup and none of its CSS.
9617
+ // While the view is being configured every entry is listed, hidden and rare ones
9618
+ // included: a hidden field a person cannot see is a field they cannot show again,
9619
+ // and «показать редкие поля» is a reading choice rather than part of the
9620
+ // arrangement being edited.
9621
+
9622
+ function listed(context, entries) {
9623
+ return context.configuring ? entries ?? [] : context.visible(entries);
9624
+ } // The chooser names the layers this person may write and nothing else. A layer
9625
+ // they may not write is drawn disabled with the host's own reason on it rather
9626
+ // than left out, because a «Для всех» that is simply absent reads as a feature
9627
+ // the product does not have.
9628
+ // The controls of the arranging mode live in the bar at the foot (owner,
9629
+ // 2026-10-08), where saving, cancelling and deleting live when a group is being
9630
+ // edited: the foot is where a mode's own answers belong, and a band of them
9631
+ // under the head pushed the record down by a row it did not need.
9632
+
9633
+
9634
+ function renderConfigureBar(context) {
9635
+ if (!context.canConfigureView) return lit__WEBPACK_IMPORTED_MODULE_0__.nothing; // Not configuring: nothing is drawn. Entering is the «⋯» menu's, as the mockup
9636
+ // has it -- a standalone «Настроить вид» link stood as its own band under the
7741
9637
  // head and was one of the two empty-looking rows the owner saw.
7742
9638
 
7743
9639
  if (!context.configuring) return lit__WEBPACK_IMPORTED_MODULE_0__.nothing; // One row of controls and nothing else: the view being arranged and the
@@ -9418,6 +11314,15 @@ function settingSetters(Class, manifest) {
9418
11314
  return Class;
9419
11315
  }
9420
11316
 
11317
+ /***/ },
11318
+
11319
+ /***/ "f59c8bcdc90a"
11320
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
11321
+
11322
+ __webpack_require__.r(__webpack_exports__);
11323
+ // extracted by mini-css-extract-plugin
11324
+
11325
+
9421
11326
  /***/ },
9422
11327
 
9423
11328
  /***/ "9e9dad7bcc09"
@@ -10396,7 +12301,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"$comment":"Dated aliases of sf-view-
10396
12301
  /***/ "3ea81f4c3c20"
10397
12302
  (module) {
10398
12303
 
10399
- module.exports = /*#__PURE__*/JSON.parse('{"id":"smart.view-properties","tag":"sf-view-properties","version":"1.10.1","kind":"leaf","implements":["record-view@1"],"settings":{"add-field-text":{"type":"string","default-from":"runtime.add-field-text"},"add-group-text":{"type":"string","default-from":"runtime.add-group-text"},"add-section-text":{"type":"string","default-from":"runtime.add-section-text"},"back-label":{"type":"string","default-from":"runtime.back-label"},"cancel-configuring-text":{"type":"string","default-from":"runtime.cancel-configuring-text"},"cancel-name-text":{"type":"string","default-from":"runtime.cancel-name-text"},"cancel-text":{"type":"string","default-from":"runtime.cancel-text"},"changed-text":{"type":"string","default-from":"runtime.changed-text"},"close-label":{"type":"string","default-from":"runtime.close-label"},"collection":{"type":"string","default":""},"collection-icon":{"type":"icon","default":""},"collection-label":{"type":"string","default":""},"configure-hint-narrow-text":{"type":"string","default-from":"runtime.configure-hint-narrow-text"},"configure-hint-text":{"type":"string","default-from":"runtime.configure-hint-text"},"configure-text":{"type":"string","default-from":"runtime.configure-text"},"conflict-text":{"type":"string","default-from":"runtime.conflict-text"},"copy-link-label":{"type":"string","default-from":"runtime.copy-link-label"},"delete-text":{"type":"string","default-from":"runtime.delete-text"},"done-configuring-text":{"type":"string","default-from":"runtime.done-configuring-text"},"edit-text":{"type":"string","default-from":"runtime.edit-text"},"empty-record-text":{"type":"string","default-from":"runtime.empty-record-text"},"empty-text":{"type":"string","default-from":"runtime.empty-text"},"errors-text":{"type":"string","default-from":"runtime.errors-text"},"favourite":{"type":"boolean","default":false},"favourite-label":{"type":"string","default-from":"runtime.favourite-label"},"field-label-text":{"type":"string","default-from":"runtime.field-label-text"},"field-settings-text":{"type":"string","default-from":"runtime.field-settings-text"},"hidden-text":{"type":"string","default-from":"runtime.hidden-text"},"hide-rare-text":{"type":"string","default-from":"runtime.hide-rare-text"},"hint-text":{"type":"string","default-from":"runtime.hint-text"},"in-this-group-text":{"type":"string","default-from":"runtime.in-this-group-text"},"inherited-text":{"type":"string","default-from":"runtime.inherited-text"},"link-copied-label":{"type":"string","default-from":"runtime.link-copied-label"},"menu-label":{"type":"string","default-from":"runtime.menu-label"},"move-down-text":{"type":"string","default-from":"runtime.move-down-text"},"move-up-text":{"type":"string","default-from":"runtime.move-up-text"},"new-group-title":{"type":"string","default-from":"runtime.new-group-title"},"new-section-title":{"type":"string","default-from":"runtime.new-section-title"},"no-match-text":{"type":"string","default-from":"runtime.no-match-text"},"open-full-label":{"type":"string","default-from":"runtime.open-full-label"},"panel":{"type":"boolean","default":false},"panel-label":{"type":"string","default":""},"panel-size":{"type":"enum","values":["1/2","1","2","full"],"default":"1"},"size":{"type":"enum","values":["1","1/2"],"default":"1"},"mode":{"type":"enum","values":["view","auto","edit","create"],"default":"auto"},"panel-width":{"type":"string","default":""},"personal-layer-text":{"type":"string","default-from":"runtime.personal-layer-text"},"rare-text":{"type":"string","default-from":"runtime.rare-text"},"record-id":{"type":"id","default":""},"remove-field-text":{"type":"string","default-from":"runtime.remove-field-text"},"remove-group-text":{"type":"string","default-from":"runtime.remove-group-text"},"remove-section-text":{"type":"string","default-from":"runtime.remove-section-text"},"rename-text":{"type":"string","default-from":"runtime.rename-text"},"reset-view-ask-text":{"type":"string","default-from":"runtime.reset-view-ask-text"},"reset-view-text":{"type":"string","default-from":"runtime.reset-view-text"},"save-name-text":{"type":"string","default-from":"runtime.save-name-text"},"save-text":{"type":"string","default-from":"runtime.save-text"},"section-icon-text":{"type":"string","default-from":"runtime.section-icon-text"},"section-icons":{"type":"string","default":""},"sections-as":{"type":"enum","values":["list","tabs"],"default":"list"},"sections-label":{"type":"string","default-from":"runtime.sections-label"},"shared-layer-text":{"type":"string","default-from":"runtime.shared-layer-text"},"show-rare":{"type":"boolean","default":false},"show-rare-text":{"type":"string","default-from":"runtime.show-rare-text"},"shown-text":{"type":"string","default-from":"runtime.shown-text"},"unplaced-hint-text":{"type":"string","default-from":"runtime.unplaced-hint-text"},"unplaced-title":{"type":"string","default-from":"runtime.unplaced-title"},"variant-text":{"type":"string","default-from":"runtime.variant-text"},"view-conflict-text":{"type":"string","default-from":"runtime.view-conflict-text"},"view-denied-text":{"type":"string","default-from":"runtime.view-denied-text"},"width-text":{"type":"string","default-from":"runtime.width-text"},"view-profile-label":{"type":"string","default-from":"runtime.view-profile-label"},"add-view-text":{"type":"string","default-from":"runtime.add-view-text"},"new-view-text":{"type":"string","default-from":"runtime.new-view-text"},"delete-view-text":{"type":"string","default-from":"runtime.delete-view-text"},"last-shared-view-text":{"type":"string","default-from":"runtime.last-shared-view-text"},"full":{"type":"boolean","default":false},"open":{"type":"boolean","default":true}},"values":{"revision":{"type":"string"},"section":{"type":"string"}},"events":{"close":{"carries":{"reason":{"type":"enum","values":["close","escape","cancelled","deleted","api"]},"record_id":{"type":"id","nullable":true},"unsaved_fields":{"type":"list"}},"cancelable":true},"open-full":{"carries":{"id":"id","address":"string","record_id":{"type":"id","nullable":true}}},"saved":{"carries":{"id":"id","revision":{"type":"string","optional":true}}},"failed":{"carries":{"reason":"string","message":{"type":"string","optional":true}}},"open":{"carries":{"field":"string","value":"object","answer":"string"}},"delete":{"carries":{"collection":"string","revision":"string","answer":"string","record_id":{"type":"id","nullable":true}}},"created":{"carries":{"collection":{"type":"string","nullable":true},"record_id":{"type":"id","nullable":true}}},"cancel":{"carries":{"mode":{"type":"enum","values":["auto","edit","create"]},"scope":{"type":"enum","values":["group"],"optional":true},"section":{"type":"string","optional":true},"group":{"type":"string","optional":true}}},"state":{"carries":{"state":"string","message":"string"},"own-verb":true},"address-copy":{"carries":{},"own-verb":true},"favourite":{"carries":{"collection":{"type":"string","nullable":true},"favourite":"boolean","record_id":{"type":"id","nullable":true}},"own-verb":true}},"actions":{"refresh":{},"load":{"with":{"reason":{"type":"string","optional":true}}},"edit-group":{"with":{"section":"string","group":"string"}},"cancel-edit":{},"save-group":{"with":{"options":{"type":"object","optional":true}},"concurrency":"drop"},"select-section":{"with":{"key":"string"}},"close-panel":{"with":{"reason":{"type":"string","optional":true}}},"copy-address":{},"open-full-page":{},"confirm-save":{},"cancel-confirmation":{}},"port":{"id":"simai.property-view-port","version":"1.17.0","contract":"src/core/contracts/ports/simai.property-view-port/1.17.0/port.json"},"presentation":{"skeleton":{"file":"skeleton.html","late":[]}},"css-variables":{"--sf-property-view--sections-width":{"type":"length","state":"default"},"--sf-property-view--title-size":{"type":"length","state":"default"},"--sf-property-view--label-size":{"type":"length","state":"default"},"--sf-property-view--value-size":{"type":"length","state":"default"},"--sf-property-view--group-size":{"type":"length","state":"default"},"--sf-property-view--edge-room":{"type":"length","state":"open"}},"host-states":{"data-state":"string","aria-busy":"string"}}');
12304
+ module.exports = /*#__PURE__*/JSON.parse('{"id":"smart.view-properties","tag":"sf-view-properties","version":"1.11.1","kind":"leaf","implements":["record-view@1"],"settings":{"add-field-text":{"type":"string","default-from":"runtime.add-field-text"},"add-group-text":{"type":"string","default-from":"runtime.add-group-text"},"add-section-text":{"type":"string","default-from":"runtime.add-section-text"},"back-label":{"type":"string","default-from":"runtime.back-label"},"cancel-configuring-text":{"type":"string","default-from":"runtime.cancel-configuring-text"},"cancel-name-text":{"type":"string","default-from":"runtime.cancel-name-text"},"cancel-text":{"type":"string","default-from":"runtime.cancel-text"},"changed-text":{"type":"string","default-from":"runtime.changed-text"},"close-label":{"type":"string","default-from":"runtime.close-label"},"collection":{"type":"string","default":""},"collection-icon":{"type":"icon","default":""},"collection-label":{"type":"string","default":""},"configure-hint-narrow-text":{"type":"string","default-from":"runtime.configure-hint-narrow-text"},"configure-hint-text":{"type":"string","default-from":"runtime.configure-hint-text"},"configure-text":{"type":"string","default-from":"runtime.configure-text"},"conflict-text":{"type":"string","default-from":"runtime.conflict-text"},"copy-link-label":{"type":"string","default-from":"runtime.copy-link-label"},"delete-text":{"type":"string","default-from":"runtime.delete-text"},"done-configuring-text":{"type":"string","default-from":"runtime.done-configuring-text"},"edit-text":{"type":"string","default-from":"runtime.edit-text"},"empty-record-text":{"type":"string","default-from":"runtime.empty-record-text"},"empty-text":{"type":"string","default-from":"runtime.empty-text"},"errors-text":{"type":"string","default-from":"runtime.errors-text"},"favourite":{"type":"boolean","default":false},"favourite-label":{"type":"string","default-from":"runtime.favourite-label"},"field-label-text":{"type":"string","default-from":"runtime.field-label-text"},"field-settings-text":{"type":"string","default-from":"runtime.field-settings-text"},"hidden-text":{"type":"string","default-from":"runtime.hidden-text"},"hide-rare-text":{"type":"string","default-from":"runtime.hide-rare-text"},"hint-text":{"type":"string","default-from":"runtime.hint-text"},"in-this-group-text":{"type":"string","default-from":"runtime.in-this-group-text"},"inherited-text":{"type":"string","default-from":"runtime.inherited-text"},"link-copied-label":{"type":"string","default-from":"runtime.link-copied-label"},"menu-label":{"type":"string","default-from":"runtime.menu-label"},"move-down-text":{"type":"string","default-from":"runtime.move-down-text"},"move-up-text":{"type":"string","default-from":"runtime.move-up-text"},"new-group-title":{"type":"string","default-from":"runtime.new-group-title"},"new-section-title":{"type":"string","default-from":"runtime.new-section-title"},"no-match-text":{"type":"string","default-from":"runtime.no-match-text"},"open-full-label":{"type":"string","default-from":"runtime.open-full-label"},"panel":{"type":"boolean","default":false},"panel-label":{"type":"string","default":""},"panel-size":{"type":"enum","values":["1/2","1","2","full"],"default":"1"},"size":{"type":"enum","values":["1","1/2"],"default":"1"},"mode":{"type":"enum","values":["view","auto","edit","create"],"default":"auto"},"panel-width":{"type":"string","default":""},"personal-layer-text":{"type":"string","default-from":"runtime.personal-layer-text"},"rare-text":{"type":"string","default-from":"runtime.rare-text"},"record-id":{"type":"id","default":""},"remove-field-text":{"type":"string","default-from":"runtime.remove-field-text"},"remove-group-text":{"type":"string","default-from":"runtime.remove-group-text"},"remove-section-text":{"type":"string","default-from":"runtime.remove-section-text"},"rename-text":{"type":"string","default-from":"runtime.rename-text"},"reset-view-ask-text":{"type":"string","default-from":"runtime.reset-view-ask-text"},"reset-view-text":{"type":"string","default-from":"runtime.reset-view-text"},"save-name-text":{"type":"string","default-from":"runtime.save-name-text"},"save-text":{"type":"string","default-from":"runtime.save-text"},"section-icon-text":{"type":"string","default-from":"runtime.section-icon-text"},"section-icons":{"type":"string","default":""},"sections-as":{"type":"enum","values":["list","tabs"],"default":"list"},"sections-label":{"type":"string","default-from":"runtime.sections-label"},"shared-layer-text":{"type":"string","default-from":"runtime.shared-layer-text"},"show-rare":{"type":"boolean","default":false},"show-rare-text":{"type":"string","default-from":"runtime.show-rare-text"},"shown-text":{"type":"string","default-from":"runtime.shown-text"},"unplaced-hint-text":{"type":"string","default-from":"runtime.unplaced-hint-text"},"unplaced-title":{"type":"string","default-from":"runtime.unplaced-title"},"variant-text":{"type":"string","default-from":"runtime.variant-text"},"view-conflict-text":{"type":"string","default-from":"runtime.view-conflict-text"},"view-denied-text":{"type":"string","default-from":"runtime.view-denied-text"},"width-text":{"type":"string","default-from":"runtime.width-text"},"view-profile-label":{"type":"string","default-from":"runtime.view-profile-label"},"add-view-text":{"type":"string","default-from":"runtime.add-view-text"},"new-view-text":{"type":"string","default-from":"runtime.new-view-text"},"delete-view-text":{"type":"string","default-from":"runtime.delete-view-text"},"last-shared-view-text":{"type":"string","default-from":"runtime.last-shared-view-text"},"full":{"type":"boolean","default":false},"open":{"type":"boolean","default":true}},"values":{"revision":{"type":"string"},"section":{"type":"string"}},"events":{"close":{"carries":{"reason":{"type":"enum","values":["close","escape","cancelled","deleted","api"]},"record_id":{"type":"id","nullable":true},"unsaved_fields":{"type":"list"}},"cancelable":true},"open-full":{"carries":{"id":"id","address":"string","record_id":{"type":"id","nullable":true}}},"saved":{"carries":{"id":"id","revision":{"type":"string","optional":true}}},"failed":{"carries":{"reason":"string","message":{"type":"string","optional":true}}},"open":{"carries":{"field":"string","value":"object","answer":"string"}},"delete":{"carries":{"collection":"string","revision":"string","answer":"string","record_id":{"type":"id","nullable":true}}},"created":{"carries":{"collection":{"type":"string","nullable":true},"record_id":{"type":"id","nullable":true}}},"cancel":{"carries":{"mode":{"type":"enum","values":["auto","edit","create"]},"scope":{"type":"enum","values":["group"],"optional":true},"section":{"type":"string","optional":true},"group":{"type":"string","optional":true}}},"state":{"carries":{"state":"string","message":"string"},"own-verb":true},"address-copy":{"carries":{},"own-verb":true},"favourite":{"carries":{"collection":{"type":"string","nullable":true},"favourite":"boolean","record_id":{"type":"id","nullable":true}},"own-verb":true}},"actions":{"refresh":{},"load":{"with":{"reason":{"type":"string","optional":true}}},"edit-group":{"with":{"section":"string","group":"string"}},"cancel-edit":{},"save-group":{"with":{"options":{"type":"object","optional":true}},"concurrency":"drop"},"select-section":{"with":{"key":"string"}},"close-panel":{"with":{"reason":{"type":"string","optional":true}}},"copy-address":{},"open-full-page":{},"confirm-save":{},"cancel-confirmation":{}},"port":{"id":"simai.property-view-port","version":"1.17.0","contract":"src/core/contracts/ports/simai.property-view-port/1.17.0/port.json"},"presentation":{"skeleton":{"file":"skeleton.html","late":[]}},"css-variables":{"--sf-property-view--sections-width":{"type":"length","state":"default"},"--sf-property-view--title-size":{"type":"length","state":"default"},"--sf-property-view--label-size":{"type":"length","state":"default"},"--sf-property-view--value-size":{"type":"length","state":"default"},"--sf-property-view--group-size":{"type":"length","state":"default"},"--sf-property-view--edge-room":{"type":"length","state":"open"}},"host-states":{"data-state":"string","aria-busy":"string"}}');
10400
12305
 
10401
12306
  /***/ },
10402
12307