@ryuzaki13/react-foundation-lib 2.26.0 → 2.28.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.
- package/dist/analytical-table/index.js +1 -1
- package/dist/browser-notifications/browserNotificationTypes.d.ts +23 -0
- package/dist/browser-notifications/browserNotificationTypes.d.ts.map +1 -0
- package/dist/browser-notifications/createBrowserNotificationPresenter.d.ts +7 -0
- package/dist/browser-notifications/createBrowserNotificationPresenter.d.ts.map +1 -0
- package/dist/browser-notifications/index.d.ts +3 -0
- package/dist/browser-notifications/index.d.ts.map +1 -0
- package/dist/browser-notifications/index.js +64 -0
- package/dist/browser-notifications/index.js.map +1 -0
- package/dist/chunks/{dom-Dbq_09-K.js → dom-BK22UmgF.js} +72 -51
- package/dist/chunks/dom-BK22UmgF.js.map +1 -0
- package/dist/chunks/{formatters-DVqfmx3V.js → formatters-B_NcT2pe.js} +2 -2
- package/dist/chunks/{formatters-DVqfmx3V.js.map → formatters-B_NcT2pe.js.map} +1 -1
- package/dist/chunks/media-WK38KtMl.js +191 -0
- package/dist/chunks/media-WK38KtMl.js.map +1 -0
- package/dist/chunks/{query-client-Dj_zNE22.js → query-client-uQEbemFc.js} +2 -2
- package/dist/chunks/{query-client-Dj_zNE22.js.map → query-client-uQEbemFc.js.map} +1 -1
- package/dist/chunks/uuid-CUJPAbRY.js +13 -0
- package/dist/chunks/uuid-CUJPAbRY.js.map +1 -0
- package/dist/crypto/index.js +18 -27
- package/dist/crypto/index.js.map +1 -1
- package/dist/dom/index.d.ts +1 -0
- package/dist/dom/index.d.ts.map +1 -1
- package/dist/dom/index.js +2 -2
- package/dist/dom/installFaviconOverride.d.ts +6 -0
- package/dist/dom/installFaviconOverride.d.ts.map +1 -0
- package/dist/error-report/index.js +14 -13
- package/dist/error-report/index.js.map +1 -1
- package/dist/excel/index.js +1 -1
- package/dist/formatters/index.js +1 -1
- package/dist/formulas/formatTableFormulaExpression.d.ts +9 -0
- package/dist/formulas/formatTableFormulaExpression.d.ts.map +1 -0
- package/dist/formulas/index.d.ts +1 -0
- package/dist/formulas/index.d.ts.map +1 -1
- package/dist/formulas/index.js +17 -9
- package/dist/formulas/index.js.map +1 -1
- package/dist/formulas/types.d.ts +2 -0
- package/dist/formulas/types.d.ts.map +1 -1
- package/dist/media/createNotificationTonePlayer.d.ts +7 -0
- package/dist/media/createNotificationTonePlayer.d.ts.map +1 -0
- package/dist/media/index.d.ts +2 -0
- package/dist/media/index.d.ts.map +1 -1
- package/dist/media/index.js +2 -148
- package/dist/media/notificationToneTypes.d.ts +13 -0
- package/dist/media/notificationToneTypes.d.ts.map +1 -0
- package/dist/query-client/index.js +1 -1
- package/dist/session-storage/index.js +1 -1
- package/dist/three-scene/index.js +1 -1
- package/package.json +5 -1
- package/src/browser-notifications/README.md +21 -0
- package/src/formulas/README.mdx +32 -1
- package/dist/chunks/dom-Dbq_09-K.js.map +0 -1
- package/dist/media/index.js.map +0 -1
package/dist/excel/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _n as e, c as t, l as n, ln as r, s as i, u as a, vn as o } from "../chunks/odata-service-tp2U5yIr.js";
|
|
2
2
|
import { t as s, v as c } from "../chunks/validate-C8cQm_9m.js";
|
|
3
|
-
import {
|
|
3
|
+
import { m as l } from "../chunks/dom-BK22UmgF.js";
|
|
4
4
|
import { escapeXmlValue as u } from "../xml/index.js";
|
|
5
5
|
import d from "write-excel-file/browser";
|
|
6
6
|
//#region src/excel/excel.ts
|
package/dist/formatters/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as e, A as t, At as n, B as r, Bt as i, C as a, Ct as o, D as s, Dt as c, E as l, Et as u, F as d, Ft as f, G as p, Gt as m, H as h, Ht as g, I as _, It as v, J as y, Jt as b, K as x, Kt as S, L as C, Lt as w, M as T, Mt as E, N as D, Nt as O, O as k, Ot as A, P as j, Pt as M, Q as N, R as P, Rt as F, S as I, St as L, T as R, Tt as z, U as B, Ut as V, V as H, Vt as U, W, Wt as G, X as K, Y as q, Z as J, _ as Y, _t as X, a as Z, at as Q, b as $, bt as ee, c as te, ct as ne, d as re, dt as ie, et as ae, f as oe, ft as se, g as ce, gt as le, h as ue, ht as de, i as fe, it as pe, j as me, jt as he, k as ge, kt as _e, l as ve, lt as ye, m as be, mt as xe, n as Se, nt as Ce, o as we, ot as Te, p as Ee, pt as De, q as Oe, qt as ke, r as Ae, rt as je, s as Me, st as Ne, t as Pe, tt as Fe, u as Ie, ut as Le, v as Re, vt as ze, w as Be, wt as Ve, x as He, xt as Ue, y as We, yt as Ge, z as Ke, zt as qe } from "../chunks/formatters-
|
|
1
|
+
import { $ as e, A as t, At as n, B as r, Bt as i, C as a, Ct as o, D as s, Dt as c, E as l, Et as u, F as d, Ft as f, G as p, Gt as m, H as h, Ht as g, I as _, It as v, J as y, Jt as b, K as x, Kt as S, L as C, Lt as w, M as T, Mt as E, N as D, Nt as O, O as k, Ot as A, P as j, Pt as M, Q as N, R as P, Rt as F, S as I, St as L, T as R, Tt as z, U as B, Ut as V, V as H, Vt as U, W, Wt as G, X as K, Y as q, Z as J, _ as Y, _t as X, a as Z, at as Q, b as $, bt as ee, c as te, ct as ne, d as re, dt as ie, et as ae, f as oe, ft as se, g as ce, gt as le, h as ue, ht as de, i as fe, it as pe, j as me, jt as he, k as ge, kt as _e, l as ve, lt as ye, m as be, mt as xe, n as Se, nt as Ce, o as we, ot as Te, p as Ee, pt as De, q as Oe, qt as ke, r as Ae, rt as je, s as Me, st as Ne, t as Pe, tt as Fe, u as Ie, ut as Le, v as Re, vt as ze, w as Be, wt as Ve, x as He, xt as Ue, y as We, yt as Ge, z as Ke, zt as qe } from "../chunks/formatters-B_NcT2pe.js";
|
|
2
2
|
import { _ as Je, b as Ye, g as Xe, v as Ze, x as Qe, y as $e } from "../chunks/array-D-_yMMUK.js";
|
|
3
3
|
import { $t as et, An as tt, Bt as nt, Cn as rt, Dn as it, En as at, Fn as ot, Gt as st, Ht as ct, It as lt, Jt as ut, Kt as dt, Lt as ft, Mn as pt, Nn as mt, On as ht, Pn as gt, Qt as _t, Rt as vt, Sn as yt, Tn as bt, Ut as xt, Vt as St, Wt as Ct, Xt as wt, Yt as Tt, Zt as Et, _n as Dt, an as Ot, bn as kt, cn as At, dn as jt, en as Mt, fn as Nt, gn as Pt, hn as Ft, in as It, jn as Lt, kn as Rt, ln as zt, mn as Bt, nn as Vt, on as Ht, pn as Ut, qt as Wt, rn as Gt, sn as Kt, tn as qt, un as Jt, vn as Yt, wn as Xt, xn as Zt, yn as Qt, zt as $t } from "../chunks/odata-service-tp2U5yIr.js";
|
|
4
4
|
import { _ as en, a as tn, b as nn, c as rn, d as an, f as on, g as sn, h as cn, i as ln, l as un, m as dn, n as fn, o as pn, p as mn, r as hn, s as gn, t as _n, u as vn, v as yn, x as bn, y as xn } from "../chunks/validate-C8cQm_9m.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Подставляет ID упорядоченных зависимостей в шаблон превью формулы.
|
|
3
|
+
*
|
|
4
|
+
* Незаданные позиции остаются в виде $n, чтобы редактор мог показывать неполный
|
|
5
|
+
* черновик. Подстановка однопроходная: ID сохраняются буквально, а полученный
|
|
6
|
+
* текст предназначен только для отображения и никогда не исполняется.
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatTableFormulaExpression(expressionTemplate: string, dependencies: readonly string[]): string;
|
|
9
|
+
//# sourceMappingURL=formatTableFormulaExpression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatTableFormulaExpression.d.ts","sourceRoot":"","sources":["../../src/formulas/formatTableFormulaExpression.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,kBAAkB,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAKhH"}
|
package/dist/formulas/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formulas/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,mBAAmB,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formulas/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,mBAAmB,SAAS,CAAC"}
|
package/dist/formulas/index.js
CHANGED
|
@@ -109,14 +109,22 @@ function c(e) {
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
//#endregion
|
|
112
|
+
//#region src/formulas/formatTableFormulaExpression.ts
|
|
113
|
+
function l(e, t) {
|
|
114
|
+
return e.replace(/\$([0-9]+)/g, (e, n) => {
|
|
115
|
+
let r = t[Number(n)];
|
|
116
|
+
return r === void 0 || r === "" ? e : r;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
112
120
|
//#region src/formulas/validate.ts
|
|
113
|
-
function
|
|
121
|
+
function u(e) {
|
|
114
122
|
return [...e].sort((e, t) => e - t);
|
|
115
123
|
}
|
|
116
|
-
function
|
|
124
|
+
function d(e, t) {
|
|
117
125
|
return e.reduce((e, n, r) => (e[n] = (r + 1) * t, e), {});
|
|
118
126
|
}
|
|
119
|
-
function
|
|
127
|
+
function f(e) {
|
|
120
128
|
let t = [], n = [], r = i(e.formulaId), a = [...e.dependencies ?? []], s = e.availableColumnIds ?? [];
|
|
121
129
|
if (!r) return t.push({
|
|
122
130
|
code: "formula_not_found",
|
|
@@ -131,10 +139,10 @@ function d(e) {
|
|
|
131
139
|
requiredDependencyCount: 0
|
|
132
140
|
}
|
|
133
141
|
};
|
|
134
|
-
let c = new Set(s),
|
|
135
|
-
|
|
142
|
+
let c = new Set(s), l = a.filter((e) => !c.has(e));
|
|
143
|
+
l.length > 0 && t.push({
|
|
136
144
|
code: "dependency_not_available",
|
|
137
|
-
message: `Не найдены среди доступных полей: ${
|
|
145
|
+
message: `Не найдены среди доступных полей: ${l.join(", ")}.`
|
|
138
146
|
});
|
|
139
147
|
let f = /* @__PURE__ */ new Set(), p = /* @__PURE__ */ new Set(), m = 0, h = (e) => {
|
|
140
148
|
try {
|
|
@@ -155,8 +163,8 @@ function d(e) {
|
|
|
155
163
|
m += 1;
|
|
156
164
|
}
|
|
157
165
|
};
|
|
158
|
-
h(
|
|
159
|
-
let g =
|
|
166
|
+
h(d(a, 100)), h(d(a, -100));
|
|
167
|
+
let g = u(f), _ = g.length > 0 ? g[g.length - 1] + 1 : 0;
|
|
160
168
|
p.size > 0 && t.push({
|
|
161
169
|
code: "dependency_index_out_of_range",
|
|
162
170
|
message: `Формула обращается к несуществующим индексам. Минимально требуется зависимостей: ${_}, выбрано: ${a.length}.`
|
|
@@ -185,6 +193,6 @@ function d(e) {
|
|
|
185
193
|
};
|
|
186
194
|
}
|
|
187
195
|
//#endregion
|
|
188
|
-
export { s as compileTableFormula, n as configureTableFormulaRegistry, o as createTableFormulaContext, e as createTableFormulaRegistry, c as executeTableFormula, i as getTableFormulaById, r as getTableFormulaList,
|
|
196
|
+
export { s as compileTableFormula, n as configureTableFormulaRegistry, o as createTableFormulaContext, e as createTableFormulaRegistry, c as executeTableFormula, l as formatTableFormulaExpression, i as getTableFormulaById, r as getTableFormulaList, f as validateTableFormulaDependencies };
|
|
189
197
|
|
|
190
198
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/formulas/registry.ts","../../src/formulas/execute.ts","../../src/formulas/validate.ts"],"sourcesContent":["import type { TableFormulaDefinition } from \"./types\";\n\nexport type TableFormulaRegistry = Readonly<{\n\tlist: readonly TableFormulaDefinition[];\n\tbyId: ReadonlyMap<string, TableFormulaDefinition>;\n}>;\n\nexport function createTableFormulaRegistry(definitions: readonly TableFormulaDefinition[]): TableFormulaRegistry {\n\tconst byId = new Map<string, TableFormulaDefinition>();\n\tconst list: TableFormulaDefinition[] = [];\n\n\tfor (const definition of definitions) {\n\t\tconst normalizedId = definition.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tthrow new Error(\"Formula id не может быть пустым\");\n\t\t}\n\n\t\tif (byId.has(normalizedId)) {\n\t\t\tthrow new Error(`Найден дублирующийся formulaId: ${normalizedId}`);\n\t\t}\n\n\t\tconst normalizedDefinition: TableFormulaDefinition = Object.freeze({\n\t\t\t...definition,\n\t\t\tid: normalizedId,\n\t\t\tname: definition.name.trim(),\n\t\t\tdescription: definition.description.trim(),\n\t\t\tkeywords: definition.keywords ? [...definition.keywords] : undefined\n\t\t});\n\n\t\tbyId.set(normalizedId, normalizedDefinition);\n\t\tlist.push(normalizedDefinition);\n\t}\n\n\treturn Object.freeze({\n\t\tlist: Object.freeze(list),\n\t\tbyId\n\t});\n}\n\nlet tableFormulaRegistry = createTableFormulaRegistry([]);\n\n/**\n * Устанавливает реестр формул host-приложения для всех formula runtime API.\n *\n * Конфигурация выполняется composition root до первого чтения, валидации или\n * компиляции формулы. Библиотека намеренно не содержит прикладной каталог.\n */\nexport function configureTableFormulaRegistry(registry: TableFormulaRegistry): void {\n\ttableFormulaRegistry = registry;\n}\n\nexport function getTableFormulaList(): readonly TableFormulaDefinition[] {\n\treturn tableFormulaRegistry.list;\n}\n\nexport function getTableFormulaById(formulaId: string | undefined): TableFormulaDefinition | undefined {\n\tconst normalizedId = formulaId?.trim();\n\tif (!normalizedId) return undefined;\n\treturn tableFormulaRegistry.byId.get(normalizedId);\n}\n","import { getTableFormulaById } from \"./registry\";\n\nimport type { TableFormulaContext, TableFormulaRowData } from \"./types\";\n\ntype TableFormulaContextInstrumentation = {\n\tonReadIndex?: (index: number) => void;\n\tonOutOfRangeIndex?: (index: number) => void;\n};\n\nfunction toFiniteNumberOrZero(value: unknown): number {\n\tconst normalized = Number(value);\n\treturn Number.isFinite(normalized) ? normalized : 0;\n}\n\nexport function createTableFormulaContext(args: {\n\trowData: TableFormulaRowData;\n\tkeys?: readonly string[];\n\tinstrumentation?: TableFormulaContextInstrumentation;\n}): TableFormulaContext {\n\t// TODO: duplicate createRowBasedFormatterContext src\\shared\\lib\\formatters\\rowBased\\context.ts\n\tconst keys = [...(args.keys ?? [])];\n\n\tconst readKey = (index: number): string | undefined => {\n\t\tif (!Number.isInteger(index) || index < 0) {\n\t\t\targs.instrumentation?.onOutOfRangeIndex?.(index);\n\t\t\treturn undefined;\n\t\t}\n\n\t\targs.instrumentation?.onReadIndex?.(index);\n\n\t\tif (index >= keys.length) {\n\t\t\targs.instrumentation?.onOutOfRangeIndex?.(index);\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn keys[index];\n\t};\n\n\tconst readValue = (index: number): unknown => {\n\t\tconst key = readKey(index);\n\t\tif (!key) return undefined;\n\t\treturn args.rowData[key];\n\t};\n\n\treturn {\n\t\tkey: readKey,\n\t\tvalue: readValue,\n\t\tnum: (index) => toFiniteNumberOrZero(readValue(index))\n\t};\n}\n\nexport type TableFormulaExecutionResult =\n\t| {\n\t\t\tok: true;\n\t\t\tvalue: number;\n\t }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"formula_not_found\" | \"invalid_result\" | \"runtime_error\";\n\t };\n\nexport type TableFormulaCompiledExecutor = (rowData: TableFormulaRowData) => TableFormulaExecutionResult;\n\ntype CompileTableFormulaResult =\n\t| {\n\t\t\tok: true;\n\t\t\texecute: TableFormulaCompiledExecutor;\n\t }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"formula_not_found\";\n\t };\n\nexport function compileTableFormula(args: { formulaId: string | undefined; keys?: readonly string[] }): CompileTableFormulaResult {\n\tconst formula = getTableFormulaById(args.formulaId);\n\tif (!formula) {\n\t\treturn { ok: false, reason: \"formula_not_found\" };\n\t}\n\n\tconst keys = [...(args.keys ?? [])];\n\tlet rowDataRef: TableFormulaRowData = {};\n\tconst context: TableFormulaContext = {\n\t\tkey: (index) => (Number.isInteger(index) && index >= 0 && index < keys.length ? keys[index] : undefined),\n\t\tvalue: (index) => {\n\t\t\tif (!Number.isInteger(index) || index < 0 || index >= keys.length) return undefined;\n\t\t\tconst key = keys[index];\n\t\t\tif (!key) return undefined;\n\t\t\treturn rowDataRef[key];\n\t\t},\n\t\tnum: (index) => {\n\t\t\tif (!Number.isInteger(index) || index < 0 || index >= keys.length) return 0;\n\t\t\tconst key = keys[index];\n\t\t\tif (!key) return 0;\n\t\t\treturn toFiniteNumberOrZero(rowDataRef[key]);\n\t\t}\n\t};\n\n\treturn {\n\t\tok: true,\n\t\texecute: (rowData) => {\n\t\t\trowDataRef = rowData;\n\n\t\t\ttry {\n\t\t\t\tconst value = formula.fn(context);\n\t\t\t\tif (!Number.isFinite(value)) {\n\t\t\t\t\treturn { ok: false, reason: \"invalid_result\" };\n\t\t\t\t}\n\n\t\t\t\treturn { ok: true, value };\n\t\t\t} catch {\n\t\t\t\treturn { ok: false, reason: \"runtime_error\" };\n\t\t\t}\n\t\t}\n\t};\n}\n\nexport function executeTableFormula(args: {\n\tformulaId: string | undefined;\n\trowData: TableFormulaRowData;\n\tkeys?: readonly string[];\n}): TableFormulaExecutionResult {\n\tconst compiled = compileTableFormula({\n\t\tformulaId: args.formulaId,\n\t\tkeys: args.keys\n\t});\n\tif (!compiled.ok) {\n\t\treturn { ok: false, reason: compiled.reason };\n\t}\n\n\treturn compiled.execute(args.rowData);\n}\n","import { createTableFormulaContext } from \"./execute\";\nimport { getTableFormulaById } from \"./registry\";\n\ntype ValidationCode =\n\t| \"formula_not_found\"\n\t| \"dependency_index_out_of_range\"\n\t| \"dependency_not_available\"\n\t| \"unused_dependencies\"\n\t| \"formula_does_not_use_dependencies\"\n\t| \"formula_runtime_error\";\n\nexport interface TableFormulaValidationMessage {\n\tcode: ValidationCode;\n\tmessage: string;\n}\nexport interface TableFormulaDependenciesValidationResult {\n\tok: boolean;\n\terrors: TableFormulaValidationMessage[];\n\twarnings: TableFormulaValidationMessage[];\n\tusage: {\n\t\tusedDependencyIndexes: number[];\n\t\tusedDependencyIds: string[];\n\t\trequiredDependencyCount: number;\n\t};\n}\n\nfunction toSortedArray(items: Set<number>): number[] {\n\treturn [...items].sort((left, right) => left - right);\n}\n\nfunction createSampleRowData(dependencies: readonly string[], multiplier: number): Record<string, unknown> {\n\treturn dependencies.reduce<Record<string, unknown>>((acc, dependencyId, index) => {\n\t\tacc[dependencyId] = (index + 1) * multiplier;\n\t\treturn acc;\n\t}, {});\n}\n\nexport function validateTableFormulaDependencies(args: {\n\tformulaId: string | undefined;\n\tdependencies?: readonly string[];\n\tavailableColumnIds?: readonly string[];\n}): TableFormulaDependenciesValidationResult {\n\tconst errors: TableFormulaValidationMessage[] = [];\n\tconst warnings: TableFormulaValidationMessage[] = [];\n\n\tconst formula = getTableFormulaById(args.formulaId);\n\tconst dependencies = [...(args.dependencies ?? [])];\n\tconst availableColumnIds = args.availableColumnIds ?? [];\n\n\tif (!formula) {\n\t\terrors.push({\n\t\t\tcode: \"formula_not_found\",\n\t\t\tmessage: \"Формула не найдена в реестре.\"\n\t\t});\n\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors,\n\t\t\twarnings,\n\t\t\tusage: {\n\t\t\t\tusedDependencyIndexes: [],\n\t\t\t\tusedDependencyIds: [],\n\t\t\t\trequiredDependencyCount: 0\n\t\t\t}\n\t\t};\n\t}\n\n\tconst availableSet = new Set(availableColumnIds);\n\tconst missingDependencies = dependencies.filter((dependencyId) => !availableSet.has(dependencyId));\n\tif (missingDependencies.length > 0) {\n\t\terrors.push({\n\t\t\tcode: \"dependency_not_available\",\n\t\t\tmessage: `Не найдены среди доступных полей: ${missingDependencies.join(\", \")}.`\n\t\t});\n\t}\n\n\tconst usedIndexes = new Set<number>();\n\tconst outOfRangeIndexes = new Set<number>();\n\tlet runtimeErrorCount = 0;\n\n\tconst runValidationPass = (sampleRowData: Record<string, unknown>) => {\n\t\ttry {\n\t\t\tconst context = createTableFormulaContext({\n\t\t\t\trowData: sampleRowData,\n\t\t\t\tkeys: dependencies,\n\t\t\t\tinstrumentation: {\n\t\t\t\t\tonReadIndex: (index) => {\n\t\t\t\t\t\tusedIndexes.add(index);\n\t\t\t\t\t},\n\t\t\t\t\tonOutOfRangeIndex: (index) => {\n\t\t\t\t\t\toutOfRangeIndexes.add(index);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tformula.fn(context);\n\t\t} catch {\n\t\t\truntimeErrorCount += 1;\n\t\t}\n\t};\n\n\t// Несколько прогонов повышают шанс увидеть обращения к индексам в разных ветках формулы.\n\trunValidationPass(createSampleRowData(dependencies, 100));\n\trunValidationPass(createSampleRowData(dependencies, -100));\n\n\tconst sortedUsedIndexes = toSortedArray(usedIndexes);\n\tconst requiredDependencyCount = sortedUsedIndexes.length > 0 ? sortedUsedIndexes[sortedUsedIndexes.length - 1] + 1 : 0;\n\n\tif (outOfRangeIndexes.size > 0) {\n\t\terrors.push({\n\t\t\tcode: \"dependency_index_out_of_range\",\n\t\t\tmessage: `Формула обращается к несуществующим индексам. Минимально требуется зависимостей: ${requiredDependencyCount}, выбрано: ${dependencies.length}.`\n\t\t});\n\t}\n\n\tif (sortedUsedIndexes.length === 0) {\n\t\twarnings.push({\n\t\t\tcode: \"formula_does_not_use_dependencies\",\n\t\t\tmessage: \"Формула не использует dependencies.\"\n\t\t});\n\t}\n\n\tconst unusedDependencies = dependencies.filter((_, index) => !usedIndexes.has(index));\n\tif (unusedDependencies.length > 0) {\n\t\twarnings.push({\n\t\t\tcode: \"unused_dependencies\",\n\t\t\tmessage: `Выбраны, но не используются формулой: ${unusedDependencies.join(\", \")}.`\n\t\t});\n\t}\n\n\tif (runtimeErrorCount > 0) {\n\t\twarnings.push({\n\t\t\tcode: \"formula_runtime_error\",\n\t\t\tmessage: \"На тестовых данных формула завершилась с ошибкой.\"\n\t\t});\n\t}\n\n\tconst usedDependencyIds = sortedUsedIndexes.map((index) => dependencies[index]).filter(Boolean);\n\n\treturn {\n\t\tok: errors.length === 0,\n\t\terrors,\n\t\twarnings,\n\t\tusage: {\n\t\t\tusedDependencyIndexes: sortedUsedIndexes,\n\t\t\tusedDependencyIds,\n\t\t\trequiredDependencyCount\n\t\t}\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/formulas/registry.ts","../../src/formulas/execute.ts","../../src/formulas/formatTableFormulaExpression.ts","../../src/formulas/validate.ts"],"sourcesContent":["import type { TableFormulaDefinition } from \"./types\";\n\nexport type TableFormulaRegistry = Readonly<{\n\tlist: readonly TableFormulaDefinition[];\n\tbyId: ReadonlyMap<string, TableFormulaDefinition>;\n}>;\n\nexport function createTableFormulaRegistry(definitions: readonly TableFormulaDefinition[]): TableFormulaRegistry {\n\tconst byId = new Map<string, TableFormulaDefinition>();\n\tconst list: TableFormulaDefinition[] = [];\n\n\tfor (const definition of definitions) {\n\t\tconst normalizedId = definition.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tthrow new Error(\"Formula id не может быть пустым\");\n\t\t}\n\n\t\tif (byId.has(normalizedId)) {\n\t\t\tthrow new Error(`Найден дублирующийся formulaId: ${normalizedId}`);\n\t\t}\n\n\t\tconst normalizedDefinition: TableFormulaDefinition = Object.freeze({\n\t\t\t...definition,\n\t\t\tid: normalizedId,\n\t\t\tname: definition.name.trim(),\n\t\t\tdescription: definition.description.trim(),\n\t\t\tkeywords: definition.keywords ? [...definition.keywords] : undefined\n\t\t});\n\n\t\tbyId.set(normalizedId, normalizedDefinition);\n\t\tlist.push(normalizedDefinition);\n\t}\n\n\treturn Object.freeze({\n\t\tlist: Object.freeze(list),\n\t\tbyId\n\t});\n}\n\nlet tableFormulaRegistry = createTableFormulaRegistry([]);\n\n/**\n * Устанавливает реестр формул host-приложения для всех formula runtime API.\n *\n * Конфигурация выполняется composition root до первого чтения, валидации или\n * компиляции формулы. Библиотека намеренно не содержит прикладной каталог.\n */\nexport function configureTableFormulaRegistry(registry: TableFormulaRegistry): void {\n\ttableFormulaRegistry = registry;\n}\n\nexport function getTableFormulaList(): readonly TableFormulaDefinition[] {\n\treturn tableFormulaRegistry.list;\n}\n\nexport function getTableFormulaById(formulaId: string | undefined): TableFormulaDefinition | undefined {\n\tconst normalizedId = formulaId?.trim();\n\tif (!normalizedId) return undefined;\n\treturn tableFormulaRegistry.byId.get(normalizedId);\n}\n","import { getTableFormulaById } from \"./registry\";\n\nimport type { TableFormulaContext, TableFormulaRowData } from \"./types\";\n\ntype TableFormulaContextInstrumentation = {\n\tonReadIndex?: (index: number) => void;\n\tonOutOfRangeIndex?: (index: number) => void;\n};\n\nfunction toFiniteNumberOrZero(value: unknown): number {\n\tconst normalized = Number(value);\n\treturn Number.isFinite(normalized) ? normalized : 0;\n}\n\nexport function createTableFormulaContext(args: {\n\trowData: TableFormulaRowData;\n\tkeys?: readonly string[];\n\tinstrumentation?: TableFormulaContextInstrumentation;\n}): TableFormulaContext {\n\t// TODO: duplicate createRowBasedFormatterContext src\\shared\\lib\\formatters\\rowBased\\context.ts\n\tconst keys = [...(args.keys ?? [])];\n\n\tconst readKey = (index: number): string | undefined => {\n\t\tif (!Number.isInteger(index) || index < 0) {\n\t\t\targs.instrumentation?.onOutOfRangeIndex?.(index);\n\t\t\treturn undefined;\n\t\t}\n\n\t\targs.instrumentation?.onReadIndex?.(index);\n\n\t\tif (index >= keys.length) {\n\t\t\targs.instrumentation?.onOutOfRangeIndex?.(index);\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn keys[index];\n\t};\n\n\tconst readValue = (index: number): unknown => {\n\t\tconst key = readKey(index);\n\t\tif (!key) return undefined;\n\t\treturn args.rowData[key];\n\t};\n\n\treturn {\n\t\tkey: readKey,\n\t\tvalue: readValue,\n\t\tnum: (index) => toFiniteNumberOrZero(readValue(index))\n\t};\n}\n\nexport type TableFormulaExecutionResult =\n\t| {\n\t\t\tok: true;\n\t\t\tvalue: number;\n\t }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"formula_not_found\" | \"invalid_result\" | \"runtime_error\";\n\t };\n\nexport type TableFormulaCompiledExecutor = (rowData: TableFormulaRowData) => TableFormulaExecutionResult;\n\ntype CompileTableFormulaResult =\n\t| {\n\t\t\tok: true;\n\t\t\texecute: TableFormulaCompiledExecutor;\n\t }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"formula_not_found\";\n\t };\n\nexport function compileTableFormula(args: { formulaId: string | undefined; keys?: readonly string[] }): CompileTableFormulaResult {\n\tconst formula = getTableFormulaById(args.formulaId);\n\tif (!formula) {\n\t\treturn { ok: false, reason: \"formula_not_found\" };\n\t}\n\n\tconst keys = [...(args.keys ?? [])];\n\tlet rowDataRef: TableFormulaRowData = {};\n\tconst context: TableFormulaContext = {\n\t\tkey: (index) => (Number.isInteger(index) && index >= 0 && index < keys.length ? keys[index] : undefined),\n\t\tvalue: (index) => {\n\t\t\tif (!Number.isInteger(index) || index < 0 || index >= keys.length) return undefined;\n\t\t\tconst key = keys[index];\n\t\t\tif (!key) return undefined;\n\t\t\treturn rowDataRef[key];\n\t\t},\n\t\tnum: (index) => {\n\t\t\tif (!Number.isInteger(index) || index < 0 || index >= keys.length) return 0;\n\t\t\tconst key = keys[index];\n\t\t\tif (!key) return 0;\n\t\t\treturn toFiniteNumberOrZero(rowDataRef[key]);\n\t\t}\n\t};\n\n\treturn {\n\t\tok: true,\n\t\texecute: (rowData) => {\n\t\t\trowDataRef = rowData;\n\n\t\t\ttry {\n\t\t\t\tconst value = formula.fn(context);\n\t\t\t\tif (!Number.isFinite(value)) {\n\t\t\t\t\treturn { ok: false, reason: \"invalid_result\" };\n\t\t\t\t}\n\n\t\t\t\treturn { ok: true, value };\n\t\t\t} catch {\n\t\t\t\treturn { ok: false, reason: \"runtime_error\" };\n\t\t\t}\n\t\t}\n\t};\n}\n\nexport function executeTableFormula(args: {\n\tformulaId: string | undefined;\n\trowData: TableFormulaRowData;\n\tkeys?: readonly string[];\n}): TableFormulaExecutionResult {\n\tconst compiled = compileTableFormula({\n\t\tformulaId: args.formulaId,\n\t\tkeys: args.keys\n\t});\n\tif (!compiled.ok) {\n\t\treturn { ok: false, reason: compiled.reason };\n\t}\n\n\treturn compiled.execute(args.rowData);\n}\n","/**\n * Подставляет ID упорядоченных зависимостей в шаблон превью формулы.\n *\n * Незаданные позиции остаются в виде $n, чтобы редактор мог показывать неполный\n * черновик. Подстановка однопроходная: ID сохраняются буквально, а полученный\n * текст предназначен только для отображения и никогда не исполняется.\n */\nexport function formatTableFormulaExpression(expressionTemplate: string, dependencies: readonly string[]): string {\n\treturn expressionTemplate.replace(/\\$([0-9]+)/g, (placeholder: string, index: string) => {\n\t\tconst dependencyId = dependencies[Number(index)];\n\t\treturn dependencyId === undefined || dependencyId === \"\" ? placeholder : dependencyId;\n\t});\n}\n","import { createTableFormulaContext } from \"./execute\";\nimport { getTableFormulaById } from \"./registry\";\n\ntype ValidationCode =\n\t| \"formula_not_found\"\n\t| \"dependency_index_out_of_range\"\n\t| \"dependency_not_available\"\n\t| \"unused_dependencies\"\n\t| \"formula_does_not_use_dependencies\"\n\t| \"formula_runtime_error\";\n\nexport interface TableFormulaValidationMessage {\n\tcode: ValidationCode;\n\tmessage: string;\n}\nexport interface TableFormulaDependenciesValidationResult {\n\tok: boolean;\n\terrors: TableFormulaValidationMessage[];\n\twarnings: TableFormulaValidationMessage[];\n\tusage: {\n\t\tusedDependencyIndexes: number[];\n\t\tusedDependencyIds: string[];\n\t\trequiredDependencyCount: number;\n\t};\n}\n\nfunction toSortedArray(items: Set<number>): number[] {\n\treturn [...items].sort((left, right) => left - right);\n}\n\nfunction createSampleRowData(dependencies: readonly string[], multiplier: number): Record<string, unknown> {\n\treturn dependencies.reduce<Record<string, unknown>>((acc, dependencyId, index) => {\n\t\tacc[dependencyId] = (index + 1) * multiplier;\n\t\treturn acc;\n\t}, {});\n}\n\nexport function validateTableFormulaDependencies(args: {\n\tformulaId: string | undefined;\n\tdependencies?: readonly string[];\n\tavailableColumnIds?: readonly string[];\n}): TableFormulaDependenciesValidationResult {\n\tconst errors: TableFormulaValidationMessage[] = [];\n\tconst warnings: TableFormulaValidationMessage[] = [];\n\n\tconst formula = getTableFormulaById(args.formulaId);\n\tconst dependencies = [...(args.dependencies ?? [])];\n\tconst availableColumnIds = args.availableColumnIds ?? [];\n\n\tif (!formula) {\n\t\terrors.push({\n\t\t\tcode: \"formula_not_found\",\n\t\t\tmessage: \"Формула не найдена в реестре.\"\n\t\t});\n\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors,\n\t\t\twarnings,\n\t\t\tusage: {\n\t\t\t\tusedDependencyIndexes: [],\n\t\t\t\tusedDependencyIds: [],\n\t\t\t\trequiredDependencyCount: 0\n\t\t\t}\n\t\t};\n\t}\n\n\tconst availableSet = new Set(availableColumnIds);\n\tconst missingDependencies = dependencies.filter((dependencyId) => !availableSet.has(dependencyId));\n\tif (missingDependencies.length > 0) {\n\t\terrors.push({\n\t\t\tcode: \"dependency_not_available\",\n\t\t\tmessage: `Не найдены среди доступных полей: ${missingDependencies.join(\", \")}.`\n\t\t});\n\t}\n\n\tconst usedIndexes = new Set<number>();\n\tconst outOfRangeIndexes = new Set<number>();\n\tlet runtimeErrorCount = 0;\n\n\tconst runValidationPass = (sampleRowData: Record<string, unknown>) => {\n\t\ttry {\n\t\t\tconst context = createTableFormulaContext({\n\t\t\t\trowData: sampleRowData,\n\t\t\t\tkeys: dependencies,\n\t\t\t\tinstrumentation: {\n\t\t\t\t\tonReadIndex: (index) => {\n\t\t\t\t\t\tusedIndexes.add(index);\n\t\t\t\t\t},\n\t\t\t\t\tonOutOfRangeIndex: (index) => {\n\t\t\t\t\t\toutOfRangeIndexes.add(index);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tformula.fn(context);\n\t\t} catch {\n\t\t\truntimeErrorCount += 1;\n\t\t}\n\t};\n\n\t// Несколько прогонов повышают шанс увидеть обращения к индексам в разных ветках формулы.\n\trunValidationPass(createSampleRowData(dependencies, 100));\n\trunValidationPass(createSampleRowData(dependencies, -100));\n\n\tconst sortedUsedIndexes = toSortedArray(usedIndexes);\n\tconst requiredDependencyCount = sortedUsedIndexes.length > 0 ? sortedUsedIndexes[sortedUsedIndexes.length - 1] + 1 : 0;\n\n\tif (outOfRangeIndexes.size > 0) {\n\t\terrors.push({\n\t\t\tcode: \"dependency_index_out_of_range\",\n\t\t\tmessage: `Формула обращается к несуществующим индексам. Минимально требуется зависимостей: ${requiredDependencyCount}, выбрано: ${dependencies.length}.`\n\t\t});\n\t}\n\n\tif (sortedUsedIndexes.length === 0) {\n\t\twarnings.push({\n\t\t\tcode: \"formula_does_not_use_dependencies\",\n\t\t\tmessage: \"Формула не использует dependencies.\"\n\t\t});\n\t}\n\n\tconst unusedDependencies = dependencies.filter((_, index) => !usedIndexes.has(index));\n\tif (unusedDependencies.length > 0) {\n\t\twarnings.push({\n\t\t\tcode: \"unused_dependencies\",\n\t\t\tmessage: `Выбраны, но не используются формулой: ${unusedDependencies.join(\", \")}.`\n\t\t});\n\t}\n\n\tif (runtimeErrorCount > 0) {\n\t\twarnings.push({\n\t\t\tcode: \"formula_runtime_error\",\n\t\t\tmessage: \"На тестовых данных формула завершилась с ошибкой.\"\n\t\t});\n\t}\n\n\tconst usedDependencyIds = sortedUsedIndexes.map((index) => dependencies[index]).filter(Boolean);\n\n\treturn {\n\t\tok: errors.length === 0,\n\t\terrors,\n\t\twarnings,\n\t\tusage: {\n\t\t\tusedDependencyIndexes: sortedUsedIndexes,\n\t\t\tusedDependencyIds,\n\t\t\trequiredDependencyCount\n\t\t}\n\t};\n}\n"],"mappings":"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"}
|
package/dist/formulas/types.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export interface TableFormulaDefinition {
|
|
|
9
9
|
id: string;
|
|
10
10
|
name: string;
|
|
11
11
|
description: string;
|
|
12
|
+
/** Шаблон превью с позициями $n; описывает выражение для человека и не участвует в выполнении fn. */
|
|
13
|
+
expressionTemplate?: string;
|
|
12
14
|
args?: readonly string[];
|
|
13
15
|
keywords?: readonly string[];
|
|
14
16
|
fn: TableFormulaFn;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/formulas/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1D,MAAM,WAAW,mBAAmB;IACnC,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC3C,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/B;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK,MAAM,CAAC;AAElE,MAAM,WAAW,sBAAsB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,EAAE,EAAE,cAAc,CAAC;CACnB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/formulas/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1D,MAAM,WAAW,mBAAmB;IACnC,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC3C,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/B;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK,MAAM,CAAC;AAElE,MAAM,WAAW,sBAAsB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,qGAAqG;IACrG,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,EAAE,EAAE,cAAc,CAAC;CACnB"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type NotificationToneNote, type NotificationTonePlayer } from "./notificationToneTypes";
|
|
2
|
+
/**
|
|
3
|
+
* Один AudioContext и ограниченный набор осцилляторов. activate вызывается из
|
|
4
|
+
* жеста пользователя; доставка сама не пытается обойти autoplay policy.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createNotificationTonePlayer(notes: readonly NotificationToneNote[]): NotificationTonePlayer;
|
|
7
|
+
//# sourceMappingURL=createNotificationTonePlayer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createNotificationTonePlayer.d.ts","sourceRoot":"","sources":["../../src/media/createNotificationTonePlayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjG;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,SAAS,oBAAoB,EAAE,GAAG,sBAAsB,CAmE3G"}
|
package/dist/media/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from "./breakpoints";
|
|
2
|
+
export { createNotificationTonePlayer } from "./createNotificationTonePlayer";
|
|
3
|
+
export { type NotificationToneNote, type NotificationTonePlayer } from "./notificationToneTypes";
|
|
2
4
|
export * from "./getCurrentFontSize";
|
|
3
5
|
export * from "./pxToEm";
|
|
4
6
|
export * from "./responsive";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjG,cAAc,sBAAsB,CAAC;AACrC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"}
|
package/dist/media/index.js
CHANGED
|
@@ -1,148 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
var n = {
|
|
4
|
-
mobileMax: 479.98 / 16,
|
|
5
|
-
tabletMin: 480 / 16,
|
|
6
|
-
tabletMax: 1151.98 / 16,
|
|
7
|
-
laptopMin: 1152 / 16
|
|
8
|
-
}, r = 16, i = 1.2;
|
|
9
|
-
function a(e) {
|
|
10
|
-
if (typeof window > "u" || typeof document > "u") return r;
|
|
11
|
-
let t = e ?? document.documentElement, n = window.getComputedStyle(t).fontSize, i = Number.parseFloat(n);
|
|
12
|
-
return !Number.isFinite(i) || i <= 0 ? r : i;
|
|
13
|
-
}
|
|
14
|
-
function o(e) {
|
|
15
|
-
if (typeof window > "u" || typeof document > "u") return i;
|
|
16
|
-
let t = e ?? document.documentElement, n = window.getComputedStyle(t).lineHeight, a = Number.parseFloat(n);
|
|
17
|
-
return !Number.isFinite(a) || a <= 0 ? i : a / r;
|
|
18
|
-
}
|
|
19
|
-
function s() {
|
|
20
|
-
return a() + o() * 10;
|
|
21
|
-
}
|
|
22
|
-
//#endregion
|
|
23
|
-
//#region src/media/pxToEm.ts
|
|
24
|
-
function c(e, t) {
|
|
25
|
-
return (e / (t ?? a())).toString();
|
|
26
|
-
}
|
|
27
|
-
//#endregion
|
|
28
|
-
//#region src/media/responsive.ts
|
|
29
|
-
function l(e) {
|
|
30
|
-
return typeof e != "object" || !e ? !1 : "mobile" in e || "tablet" in e || "laptop" in e || "desktop" in e;
|
|
31
|
-
}
|
|
32
|
-
function u(e, t) {
|
|
33
|
-
if (e !== void 0) return l(e) ? t === "mobile" ? e.mobile ?? e.tablet ?? e.laptop : t === "tablet" ? e.tablet ?? e.mobile ?? e.laptop : e.laptop ?? e.tablet ?? e.mobile : e;
|
|
34
|
-
}
|
|
35
|
-
function d(e, t, n) {
|
|
36
|
-
let r = { ...e };
|
|
37
|
-
for (let e of n) r[e] = u(r[e], t);
|
|
38
|
-
return r;
|
|
39
|
-
}
|
|
40
|
-
//#endregion
|
|
41
|
-
//#region src/media/useMediaQuery.ts
|
|
42
|
-
var f = () => {};
|
|
43
|
-
function p(e, t) {
|
|
44
|
-
return typeof window > "u" || typeof window.matchMedia != "function" ? t : window.matchMedia(e).matches;
|
|
45
|
-
}
|
|
46
|
-
function m(e, t) {
|
|
47
|
-
if (typeof window > "u" || typeof window.matchMedia != "function") return f;
|
|
48
|
-
let n = window.matchMedia(e);
|
|
49
|
-
return typeof n.addEventListener == "function" ? (n.addEventListener("change", t), () => n.removeEventListener("change", t)) : (n.addListener(t), () => n.removeListener(t));
|
|
50
|
-
}
|
|
51
|
-
function h(n, { ssrFallback: r = !1 } = {}) {
|
|
52
|
-
let i = e((e) => m(n, e), [n]), a = e(() => p(n, r), [n, r]), o = e(() => r, [r]);
|
|
53
|
-
return t(i, a, o);
|
|
54
|
-
}
|
|
55
|
-
//#endregion
|
|
56
|
-
//#region src/media/useMatchMedia.ts
|
|
57
|
-
function g(e, t) {
|
|
58
|
-
return "addEventListener" in e ? (e.addEventListener("change", t), () => e.removeEventListener("change", t)) : (e.addListener(t), () => e.removeListener(t));
|
|
59
|
-
}
|
|
60
|
-
function _(e) {
|
|
61
|
-
let t = (t) => t * e, r = t(n.mobileMax), i = t(n.tabletMin), a = t(n.tabletMax), o = t(n.laptopMin);
|
|
62
|
-
return {
|
|
63
|
-
mobile: `(width <= ${r}px)`,
|
|
64
|
-
tablet: `(width >= ${i}px) and (width <= ${a}px)`,
|
|
65
|
-
laptop: `(width >= ${o}px)`
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
var v = {
|
|
69
|
-
matches: {
|
|
70
|
-
mobile: !1,
|
|
71
|
-
tablet: !1,
|
|
72
|
-
laptop: !1
|
|
73
|
-
},
|
|
74
|
-
activeBreakpoint: "laptop"
|
|
75
|
-
}, y = .25, b = 80, x = v, S = null, C = [], w = 0, T = !1, E = null, D = null, O = null, k = null, A = /* @__PURE__ */ new Set();
|
|
76
|
-
function j(e) {
|
|
77
|
-
return e.mobile ? "mobile" : e.tablet ? "tablet" : "laptop";
|
|
78
|
-
}
|
|
79
|
-
function M(e, t) {
|
|
80
|
-
return e.mobile === t.mobile && e.tablet === t.tablet && e.laptop === t.laptop;
|
|
81
|
-
}
|
|
82
|
-
function N(e) {
|
|
83
|
-
M(x.matches, e) || (x = {
|
|
84
|
-
matches: e,
|
|
85
|
-
activeBreakpoint: j(e)
|
|
86
|
-
}, A.forEach((e) => e()));
|
|
87
|
-
}
|
|
88
|
-
function P() {
|
|
89
|
-
S && N({
|
|
90
|
-
mobile: S.mobile.matches,
|
|
91
|
-
tablet: S.tablet.matches,
|
|
92
|
-
laptop: S.laptop.matches
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
function F() {
|
|
96
|
-
C.forEach((e) => e()), C = [];
|
|
97
|
-
}
|
|
98
|
-
function I(e = !1) {
|
|
99
|
-
if (typeof window > "u" || typeof document > "u") return;
|
|
100
|
-
let t = a();
|
|
101
|
-
if (!e && S && Math.abs(t - w) < y) return;
|
|
102
|
-
w = t, F();
|
|
103
|
-
let n = _(t);
|
|
104
|
-
S = {
|
|
105
|
-
mobile: window.matchMedia(n.mobile),
|
|
106
|
-
tablet: window.matchMedia(n.tablet),
|
|
107
|
-
laptop: window.matchMedia(n.laptop)
|
|
108
|
-
}, C = Object.keys(S).map((e) => g(S[e], P)), P();
|
|
109
|
-
}
|
|
110
|
-
function L() {
|
|
111
|
-
k && clearTimeout(k), k = setTimeout(() => {
|
|
112
|
-
k = null, I();
|
|
113
|
-
}, b);
|
|
114
|
-
}
|
|
115
|
-
function R() {
|
|
116
|
-
typeof window > "u" || typeof document > "u" || (E = new MutationObserver(L), E.observe(document.documentElement, {
|
|
117
|
-
attributes: !0,
|
|
118
|
-
attributeFilter: [
|
|
119
|
-
"style",
|
|
120
|
-
"class",
|
|
121
|
-
"data-font-size"
|
|
122
|
-
]
|
|
123
|
-
}), !(typeof ResizeObserver > "u") && (O = document.createElement("div"), O.style.position = "absolute", O.style.visibility = "hidden", O.style.pointerEvents = "none", O.style.width = "1em", O.style.height = "1px", O.style.overflow = "hidden", O.setAttribute("aria-hidden", "true"), (document.body ?? document.documentElement).appendChild(O), D = new ResizeObserver(L), D.observe(O)));
|
|
124
|
-
}
|
|
125
|
-
function z() {
|
|
126
|
-
F(), S = null, k &&= (clearTimeout(k), null), E &&= (E.disconnect(), null), D &&= (D.disconnect(), null), O?.parentNode && O.parentNode.removeChild(O), O = null, T = !1;
|
|
127
|
-
}
|
|
128
|
-
function B() {
|
|
129
|
-
T || typeof window > "u" || typeof document > "u" || (T = !0, I(!0), R());
|
|
130
|
-
}
|
|
131
|
-
function V(e) {
|
|
132
|
-
return typeof window > "u" || typeof document > "u" ? () => {} : (A.add(e), B(), () => {
|
|
133
|
-
A.delete(e), A.size === 0 && z();
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
function H() {
|
|
137
|
-
return x;
|
|
138
|
-
}
|
|
139
|
-
function U() {
|
|
140
|
-
return v;
|
|
141
|
-
}
|
|
142
|
-
function W() {
|
|
143
|
-
return t(V, H, U);
|
|
144
|
-
}
|
|
145
|
-
//#endregion
|
|
146
|
-
export { n as BREAKPOINTS_EM, s as getControlHeight, a as getCurrentFontSize, o as getCurrentLineHeight, l as isResponsiveMap, c as pxToEm, d as resolveProps, u as resolveResponsiveValue, W as useMatchMedia, h as useMediaQuery };
|
|
147
|
-
|
|
148
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import { a as e, c as t, d as n, i as r, l as i, n as a, o, r as s, s as c, t as l, u } from "../chunks/media-WK38KtMl.js";
|
|
2
|
+
export { n as BREAKPOINTS_EM, u as createNotificationTonePlayer, c as getControlHeight, t as getCurrentFontSize, i as getCurrentLineHeight, s as isResponsiveMap, o as pxToEm, r as resolveProps, e as resolveResponsiveValue, l as useMatchMedia, a as useMediaQuery };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Ноты синтезированного сигнала; временные значения заданы в секундах. */
|
|
2
|
+
export type NotificationToneNote = Readonly<{
|
|
3
|
+
frequency: number;
|
|
4
|
+
offset: number;
|
|
5
|
+
duration: number;
|
|
6
|
+
volume: number;
|
|
7
|
+
}>;
|
|
8
|
+
export type NotificationTonePlayer = Readonly<{
|
|
9
|
+
activate: () => Promise<boolean>;
|
|
10
|
+
play: () => boolean;
|
|
11
|
+
dispose: () => void;
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=notificationToneTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notificationToneTypes.d.ts","sourceRoot":"","sources":["../../src/media/notificationToneTypes.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC7C,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,EAAE,MAAM,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as e, D as t, E as n, S as r, T as i, _ as a, a as o, b as s, c, d as l, f as u, g as d, h as f, i as p, l as m, m as h, n as g, o as _, p as v, r as y, s as b, t as x, u as S, v as C, w, x as T, y as E } from "../chunks/query-client-
|
|
1
|
+
import { C as e, D as t, E as n, S as r, T as i, _ as a, a as o, b as s, c, d as l, f as u, g as d, h as f, i as p, l as m, m as h, n as g, o as _, p as v, r as y, s as b, t as x, u as S, v as C, w, x as T, y as E } from "../chunks/query-client-uQEbemFc.js";
|
|
2
2
|
export { s as QUERY_RESTORED_DATA_PARSER, S as REACT_QUERY_PERSISTENCE_BUSTER, l as REACT_QUERY_PERSISTENCE_MAX_AGE, i as broadcastCacheEvent, u as clearSessionQueryPersistence, C as configureQueryPersistenceProjectAdapter, v as createIndexedDbQueryStorage, o as createQueryClient, h as createReactQueryPersister, T as createSessionQueryPersistenceMeta, E as getQueryPersistenceProjectAdapter, f as getSessionQueryPersistenceScope, w as installQueryInvalidationBroadcast, n as installReactQueryBroadcast, x as installSessionScopedQueryReset, p as installSessionScopedQueryResetLifecycle, g as isSessionScopedQuery, _ as onErrorOptimistic, b as onMutateOptimistic, c as onSettledOptimistic, m as onSuccessOptimistic, r as persistedQueryMeta, y as resetSessionScopedQueries, e as sessionScopedQueryMeta, t as setBroadcastFn, d as setSessionQueryPersistenceScope, a as shouldPersistQuery };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ryuzaki13/react-foundation-lib",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.28.0",
|
|
4
4
|
"description": "Reusable React and TypeScript foundation utilities, hooks, and primitives.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ryuzaki13",
|
|
@@ -49,6 +49,10 @@
|
|
|
49
49
|
"types": "./dist/binary/index.d.ts",
|
|
50
50
|
"import": "./dist/binary/index.js"
|
|
51
51
|
},
|
|
52
|
+
"./browser-notifications": {
|
|
53
|
+
"types": "./dist/browser-notifications/index.d.ts",
|
|
54
|
+
"import": "./dist/browser-notifications/index.js"
|
|
55
|
+
},
|
|
52
56
|
"./bounded-copy-stack": {
|
|
53
57
|
"types": "./dist/bounded-copy-stack/index.d.ts",
|
|
54
58
|
"import": "./dist/bounded-copy-stack/index.js"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Браузерные уведомления
|
|
2
|
+
|
|
3
|
+
`createBrowserNotificationPresenter` из `/browser-notifications` предоставляет
|
|
4
|
+
явный запрос разрешения и отменяемую публикацию системного уведомления.
|
|
5
|
+
Создание не обращается к браузеру; SSR не вызывает API. Метод `show` предпочитает
|
|
6
|
+
уже активный Service Worker, а без него использует desktop Notification API.
|
|
7
|
+
Приложение обрабатывает `notificationclick` своего worker, проверяя URL из data.
|
|
8
|
+
Серверная Web Push доставка и регистрация worker не входят в контракт.
|
|
9
|
+
|
|
10
|
+
`requestPermission` вызывается непосредственно из пользовательского жеста.
|
|
11
|
+
Отказ не запрашивается повторно. HTTPS/localhost и поддержка API обязательны;
|
|
12
|
+
системные ограничения остаются у браузера. `show` возвращает немедленный disposer,
|
|
13
|
+
который закрывает также позднюю SW-публикацию; `dispose` завершает все свои.
|
|
14
|
+
События клика desktop передаются в `onOpen`, ошибки доставки — в `onError`.
|
|
15
|
+
|
|
16
|
+
Связанные независимые primitives: `/media` экспортирует
|
|
17
|
+
`createNotificationTonePlayer` с плавным синусоидальным сигналом до 1,5 секунды
|
|
18
|
+
и явной `activate` из жеста пользователя; `/dom` предоставляет
|
|
19
|
+
`installFaviconOverride` с симметричным восстановлением favicon links.
|
|
20
|
+
Продуктовые правила, интервалы оповещения, тексты, настройки и дедупликация
|
|
21
|
+
остаются у вызывающего приложения.
|
package/src/formulas/README.mdx
CHANGED
|
@@ -45,6 +45,7 @@ import { Meta } from "@storybook/addon-docs/blocks";
|
|
|
45
45
|
|
|
46
46
|
- описывает типизированный контракт числовой формулы;
|
|
47
47
|
- связывает dependency indexes с полями текущей строки;
|
|
48
|
+
- формирует текстовое превью выражения с ID выбранных зависимостей;
|
|
48
49
|
- создаёт нормализованный реестр формул host-приложения;
|
|
49
50
|
- хранит один активный реестр в текущем экземпляре модуля;
|
|
50
51
|
- выполняет формулы без выбрасывания их runtime-ошибок наружу;
|
|
@@ -81,6 +82,7 @@ import {
|
|
|
81
82
|
executeTableFormula,
|
|
82
83
|
getTableFormulaById,
|
|
83
84
|
getTableFormulaList,
|
|
85
|
+
formatTableFormulaExpression,
|
|
84
86
|
validateTableFormulaDependencies
|
|
85
87
|
} from "@ryuzaki13/react-foundation-lib/formulas";
|
|
86
88
|
|
|
@@ -222,6 +224,7 @@ interface TableFormulaDefinition {
|
|
|
222
224
|
id: string;
|
|
223
225
|
name: string;
|
|
224
226
|
description: string;
|
|
227
|
+
expressionTemplate?: string;
|
|
225
228
|
args?: readonly string[];
|
|
226
229
|
keywords?: readonly string[];
|
|
227
230
|
fn: TableFormulaFn;
|
|
@@ -266,6 +269,33 @@ description: "100 * $0 / ($0 + $1)";
|
|
|
266
269
|
|
|
267
270
|
Factory trim-ит строку, но не анализирует выражение. `$0`, `$1` — только принятая человеком нотация документации, а не parser syntax.
|
|
268
271
|
|
|
272
|
+
### `expressionTemplate`
|
|
273
|
+
|
|
274
|
+
Необязательный шаблон компактного превью. В отличие от `description`, он содержит только отображаемое выражение:
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
expressionTemplate: "$0 / $1";
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Индекс `$n` соответствует позиции в упорядоченном списке зависимостей. Шаблон сохраняется буквально; registry, execution и validation не требуют его наличия. Ранее объявленные definitions без этого поля сохраняют прежний контракт.
|
|
281
|
+
|
|
282
|
+
Шаблон служит описанием основной операции для человека. Он не заменяет `fn`, не исполняется и не обязан воспроизводить все защитные ветвления функции, например возврат нуля при нулевом делителе. За соответствие шаблона операции отвечает автор definition.
|
|
283
|
+
|
|
284
|
+
### `formatTableFormulaExpression(expressionTemplate, dependencies)`
|
|
285
|
+
|
|
286
|
+
Чистая функция подставляет ID зависимостей в позиции `$n` за один проход:
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
import { formatTableFormulaExpression } from "@ryuzaki13/react-foundation-lib/formulas";
|
|
290
|
+
|
|
291
|
+
formatTableFormulaExpression("$0 / $1", ["FIELD_X", "FIELD_Y"]); // "FIELD_X / FIELD_Y"
|
|
292
|
+
formatTableFormulaExpression("$0 / $1", ["FIELD_X"]); // "FIELD_X / $1"
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Повторные вхождения заменяются, `$1` и `$10` различаются. Незаданный или пустой ID оставляет исходный маркер; пробелы и специальные символы в ID сохраняются. Подставленные ID не обрабатываются повторно, входной массив не изменяется. Операторы, скобки и остальной текст шаблона не анализируются.
|
|
296
|
+
|
|
297
|
+
Пустая строка возвращается без изменений. Host UI самостоятельно выбирает сообщение для отсутствующего или пустого шаблона и отображает результат как текст.
|
|
298
|
+
|
|
269
299
|
### `args`
|
|
270
300
|
|
|
271
301
|
Необязательные подписи positional arguments:
|
|
@@ -1035,7 +1065,7 @@ app composition / registries
|
|
|
1035
1065
|
- TypeScript проверяет написанные definitions;
|
|
1036
1066
|
- обычные unit-tests видят функцию напрямую.
|
|
1037
1067
|
|
|
1038
|
-
`description`
|
|
1068
|
+
`description` и `expressionTemplate` могут содержать формулу для человека, но runtime выполняет только `fn`, заранее включённую разработчиком в registry.
|
|
1039
1069
|
|
|
1040
1070
|
### Доверенный код всё равно требует дисциплины
|
|
1041
1071
|
|
|
@@ -1204,6 +1234,7 @@ Promise не является конечным number и даст `invalid_resul
|
|
|
1204
1234
|
| `configureTableFormulaRegistry` | Установить активный registry | Полностью заменяет module-level registry |
|
|
1205
1235
|
| `getTableFormulaList` | Получить ordered catalog | Возвращает тот же readonly list |
|
|
1206
1236
|
| `getTableFormulaById` | Найти definition | Trim id; `undefined` для пустого/неизвестного |
|
|
1237
|
+
| `formatTableFormulaExpression` | Подставить ID в шаблон превью | Сохраняет незаполненные `$n`; не исполняет выражение |
|
|
1207
1238
|
| `compileTableFormula` | Подготовить reusable executor | Фиксирует formula и копирует keys |
|
|
1208
1239
|
| `executeTableFormula` | Compile + один execute | Возвращает controlled result, не бросает formula error |
|
|
1209
1240
|
| `validateTableFormulaDependencies` | Проверить mapping dependencies | Дважды исполняет formula на synthetic data |
|