@ifc-lite/rules 0.2.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 (179) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +45 -0
  3. package/dist/engine/rule-engine-chunk.d.ts +25 -0
  4. package/dist/engine/rule-engine-chunk.d.ts.map +1 -0
  5. package/dist/engine/rule-engine-chunk.js +43 -0
  6. package/dist/engine/rule-engine-chunk.js.map +1 -0
  7. package/dist/engine/rule-engine-compare.d.ts +17 -0
  8. package/dist/engine/rule-engine-compare.d.ts.map +1 -0
  9. package/dist/engine/rule-engine-compare.js +69 -0
  10. package/dist/engine/rule-engine-compare.js.map +1 -0
  11. package/dist/engine/rule-engine-requirements.d.ts +37 -0
  12. package/dist/engine/rule-engine-requirements.d.ts.map +1 -0
  13. package/dist/engine/rule-engine-requirements.js +293 -0
  14. package/dist/engine/rule-engine-requirements.js.map +1 -0
  15. package/dist/engine/rule-engine-sets.d.ts +46 -0
  16. package/dist/engine/rule-engine-sets.d.ts.map +1 -0
  17. package/dist/engine/rule-engine-sets.js +298 -0
  18. package/dist/engine/rule-engine-sets.js.map +1 -0
  19. package/dist/engine/rule-engine-unit.d.ts +23 -0
  20. package/dist/engine/rule-engine-unit.d.ts.map +1 -0
  21. package/dist/engine/rule-engine-unit.js +64 -0
  22. package/dist/engine/rule-engine-unit.js.map +1 -0
  23. package/dist/engine/rule-engine.d.ts +29 -0
  24. package/dist/engine/rule-engine.d.ts.map +1 -0
  25. package/dist/engine/rule-engine.js +244 -0
  26. package/dist/engine/rule-engine.js.map +1 -0
  27. package/dist/filter/effective-filter-fields.d.ts +13 -0
  28. package/dist/filter/effective-filter-fields.d.ts.map +1 -0
  29. package/dist/filter/effective-filter-fields.js +44 -0
  30. package/dist/filter/effective-filter-fields.js.map +1 -0
  31. package/dist/filter/entity-predefined-type.d.ts +24 -0
  32. package/dist/filter/entity-predefined-type.d.ts.map +1 -0
  33. package/dist/filter/entity-predefined-type.js +34 -0
  34. package/dist/filter/entity-predefined-type.js.map +1 -0
  35. package/dist/filter/filter-evaluate-groups.d.ts +36 -0
  36. package/dist/filter/filter-evaluate-groups.d.ts.map +1 -0
  37. package/dist/filter/filter-evaluate-groups.js +111 -0
  38. package/dist/filter/filter-evaluate-groups.js.map +1 -0
  39. package/dist/filter/filter-evaluate-model-tag.d.ts +22 -0
  40. package/dist/filter/filter-evaluate-model-tag.d.ts.map +1 -0
  41. package/dist/filter/filter-evaluate-model-tag.js +35 -0
  42. package/dist/filter/filter-evaluate-model-tag.js.map +1 -0
  43. package/dist/filter/filter-evaluate-mutations.d.ts +51 -0
  44. package/dist/filter/filter-evaluate-mutations.d.ts.map +1 -0
  45. package/dist/filter/filter-evaluate-mutations.js +111 -0
  46. package/dist/filter/filter-evaluate-mutations.js.map +1 -0
  47. package/dist/filter/filter-evaluate-yield.d.ts +9 -0
  48. package/dist/filter/filter-evaluate-yield.d.ts.map +1 -0
  49. package/dist/filter/filter-evaluate-yield.js +32 -0
  50. package/dist/filter/filter-evaluate-yield.js.map +1 -0
  51. package/dist/filter/filter-evaluate.d.ts +120 -0
  52. package/dist/filter/filter-evaluate.d.ts.map +1 -0
  53. package/dist/filter/filter-evaluate.js +408 -0
  54. package/dist/filter/filter-evaluate.js.map +1 -0
  55. package/dist/filter/filter-group-rule.d.ts +23 -0
  56. package/dist/filter/filter-group-rule.d.ts.map +1 -0
  57. package/dist/filter/filter-group-rule.js +69 -0
  58. package/dist/filter/filter-group-rule.js.map +1 -0
  59. package/dist/filter/filter-groups.d.ts +65 -0
  60. package/dist/filter/filter-groups.d.ts.map +1 -0
  61. package/dist/filter/filter-groups.js +136 -0
  62. package/dist/filter/filter-groups.js.map +1 -0
  63. package/dist/filter/filter-iteration-source.d.ts +26 -0
  64. package/dist/filter/filter-iteration-source.d.ts.map +1 -0
  65. package/dist/filter/filter-iteration-source.js +154 -0
  66. package/dist/filter/filter-iteration-source.js.map +1 -0
  67. package/dist/filter/filter-iteration.d.ts +5 -0
  68. package/dist/filter/filter-iteration.d.ts.map +1 -0
  69. package/dist/filter/filter-iteration.js +25 -0
  70. package/dist/filter/filter-iteration.js.map +1 -0
  71. package/dist/filter/filter-match.d.ts +114 -0
  72. package/dist/filter/filter-match.d.ts.map +1 -0
  73. package/dist/filter/filter-match.js +302 -0
  74. package/dist/filter/filter-match.js.map +1 -0
  75. package/dist/filter/filter-ops.d.ts +90 -0
  76. package/dist/filter/filter-ops.d.ts.map +1 -0
  77. package/dist/filter/filter-ops.js +202 -0
  78. package/dist/filter/filter-ops.js.map +1 -0
  79. package/dist/filter/filter-rule-guards.d.ts +4 -0
  80. package/dist/filter/filter-rule-guards.d.ts.map +1 -0
  81. package/dist/filter/filter-rule-guards.js +74 -0
  82. package/dist/filter/filter-rule-guards.js.map +1 -0
  83. package/dist/filter/filter-rules.d.ts +275 -0
  84. package/dist/filter/filter-rules.d.ts.map +1 -0
  85. package/dist/filter/filter-rules.js +68 -0
  86. package/dist/filter/filter-rules.js.map +1 -0
  87. package/dist/filter/lens-material-names.d.ts +13 -0
  88. package/dist/filter/lens-material-names.d.ts.map +1 -0
  89. package/dist/filter/lens-material-names.js +36 -0
  90. package/dist/filter/lens-material-names.js.map +1 -0
  91. package/dist/filter/measure-units.d.ts +29 -0
  92. package/dist/filter/measure-units.d.ts.map +1 -0
  93. package/dist/filter/measure-units.js +72 -0
  94. package/dist/filter/measure-units.js.map +1 -0
  95. package/dist/filter/model-tag.d.ts +65 -0
  96. package/dist/filter/model-tag.d.ts.map +1 -0
  97. package/dist/filter/model-tag.js +57 -0
  98. package/dist/filter/model-tag.js.map +1 -0
  99. package/dist/filter/read-measure-subject.d.ts +28 -0
  100. package/dist/filter/read-measure-subject.d.ts.map +1 -0
  101. package/dist/filter/read-measure-subject.js +116 -0
  102. package/dist/filter/read-measure-subject.js.map +1 -0
  103. package/dist/filter/read-subject.d.ts +72 -0
  104. package/dist/filter/read-subject.d.ts.map +1 -0
  105. package/dist/filter/read-subject.js +128 -0
  106. package/dist/filter/read-subject.js.map +1 -0
  107. package/dist/filter/subject-match.d.ts +27 -0
  108. package/dist/filter/subject-match.d.ts.map +1 -0
  109. package/dist/filter/subject-match.js +52 -0
  110. package/dist/filter/subject-match.js.map +1 -0
  111. package/dist/filter/subject-read-options.d.ts +33 -0
  112. package/dist/filter/subject-read-options.d.ts.map +1 -0
  113. package/dist/filter/subject-read-options.js +8 -0
  114. package/dist/filter/subject-read-options.js.map +1 -0
  115. package/dist/ids/ids-facet-to-rules.d.ts +20 -0
  116. package/dist/ids/ids-facet-to-rules.d.ts.map +1 -0
  117. package/dist/ids/ids-facet-to-rules.js +230 -0
  118. package/dist/ids/ids-facet-to-rules.js.map +1 -0
  119. package/dist/ids/ids-regex.d.ts +44 -0
  120. package/dist/ids/ids-regex.d.ts.map +1 -0
  121. package/dist/ids/ids-regex.js +334 -0
  122. package/dist/ids/ids-regex.js.map +1 -0
  123. package/dist/ids/ids-to-rule-set.d.ts +39 -0
  124. package/dist/ids/ids-to-rule-set.d.ts.map +1 -0
  125. package/dist/ids/ids-to-rule-set.js +103 -0
  126. package/dist/ids/ids-to-rule-set.js.map +1 -0
  127. package/dist/ids/ids-xml-writer.d.ts +11 -0
  128. package/dist/ids/ids-xml-writer.d.ts.map +1 -0
  129. package/dist/ids/ids-xml-writer.js +172 -0
  130. package/dist/ids/ids-xml-writer.js.map +1 -0
  131. package/dist/ids/rule-set-to-ids.d.ts +45 -0
  132. package/dist/ids/rule-set-to-ids.d.ts.map +1 -0
  133. package/dist/ids/rule-set-to-ids.js +140 -0
  134. package/dist/ids/rule-set-to-ids.js.map +1 -0
  135. package/dist/ids/rule-to-ids-facets.d.ts +52 -0
  136. package/dist/ids/rule-to-ids-facets.d.ts.map +1 -0
  137. package/dist/ids/rule-to-ids-facets.js +291 -0
  138. package/dist/ids/rule-to-ids-facets.js.map +1 -0
  139. package/dist/ids/stored-unit-scale.d.ts +15 -0
  140. package/dist/ids/stored-unit-scale.d.ts.map +1 -0
  141. package/dist/ids/stored-unit-scale.js +64 -0
  142. package/dist/ids/stored-unit-scale.js.map +1 -0
  143. package/dist/index.d.ts +39 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +46 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/rule-set/between-chip.d.ts +54 -0
  148. package/dist/rule-set/between-chip.d.ts.map +1 -0
  149. package/dist/rule-set/between-chip.js +95 -0
  150. package/dist/rule-set/between-chip.js.map +1 -0
  151. package/dist/rule-set/requirement-invariants.d.ts +25 -0
  152. package/dist/rule-set/requirement-invariants.d.ts.map +1 -0
  153. package/dist/rule-set/requirement-invariants.js +29 -0
  154. package/dist/rule-set/requirement-invariants.js.map +1 -0
  155. package/dist/rule-set/requirement-text.d.ts +20 -0
  156. package/dist/rule-set/requirement-text.d.ts.map +1 -0
  157. package/dist/rule-set/requirement-text.js +179 -0
  158. package/dist/rule-set/requirement-text.js.map +1 -0
  159. package/dist/rule-set/rule-set-io-requirement.d.ts +22 -0
  160. package/dist/rule-set/rule-set-io-requirement.d.ts.map +1 -0
  161. package/dist/rule-set/rule-set-io-requirement.js +140 -0
  162. package/dist/rule-set/rule-set-io-requirement.js.map +1 -0
  163. package/dist/rule-set/rule-set-io-shared.d.ts +24 -0
  164. package/dist/rule-set/rule-set-io-shared.d.ts.map +1 -0
  165. package/dist/rule-set/rule-set-io-shared.js +48 -0
  166. package/dist/rule-set/rule-set-io-shared.js.map +1 -0
  167. package/dist/rule-set/rule-set-io-subject.d.ts +10 -0
  168. package/dist/rule-set/rule-set-io-subject.d.ts.map +1 -0
  169. package/dist/rule-set/rule-set-io-subject.js +67 -0
  170. package/dist/rule-set/rule-set-io-subject.js.map +1 -0
  171. package/dist/rule-set/rule-set-io.d.ts +37 -0
  172. package/dist/rule-set/rule-set-io.d.ts.map +1 -0
  173. package/dist/rule-set/rule-set-io.js +142 -0
  174. package/dist/rule-set/rule-set-io.js.map +1 -0
  175. package/dist/rule-set/rule-set.d.ts +109 -0
  176. package/dist/rule-set/rule-set.d.ts.map +1 -0
  177. package/dist/rule-set/rule-set.js +5 -0
  178. package/dist/rule-set/rule-set.js.map +1 -0
  179. package/package.json +59 -0
@@ -0,0 +1,74 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * JSON guards for `FilterRule` (saved filters, URL state, presets).
6
+ *
7
+ * Split out of `filter-rules.ts` (which keeps the taxonomy itself — the
8
+ * interfaces and the `Rule` convenience constructors) to stay under the
9
+ * module size cap, the same way `filter-match.ts`/`filter-iteration-source.ts`
10
+ * split out of `filter-evaluate.ts`. Re-exported from `filter-rules.ts` so
11
+ * every existing `import { isFilterRule } from './filter-rules.js'` keeps
12
+ * working unchanged.
13
+ */
14
+ import { isModelTagOp } from './model-tag.js';
15
+ const STRING_OPS = new Set([
16
+ 'eq', 'ne', 'contains', 'notContains', 'startsWith', 'matches', 'notMatches',
17
+ ]);
18
+ const CLASSIFICATION_OPS = new Set([
19
+ 'eq', 'ne', 'contains', 'notContains', 'matches', 'notMatches', 'isSet', 'isNotSet',
20
+ ]);
21
+ export function isFilterRule(value) {
22
+ if (typeof value !== 'object' || value === null)
23
+ return false;
24
+ const kind = value.kind;
25
+ if (kind === 'modelTag') {
26
+ // Structural: a bad op or a non-string id must not reach the evaluator.
27
+ const r = value;
28
+ return isModelTagOp(r.op) && Array.isArray(r.tagIds) && r.tagIds.every((t) => typeof t === 'string');
29
+ }
30
+ if (kind === 'parent') {
31
+ // Structural: `matchParentRule` lower-cases `value` per ancestor, so a
32
+ // persisted non-string value (or an unknown op) must not reach it.
33
+ const r = value;
34
+ return (STRING_OPS.has(r.op) &&
35
+ typeof r.value === 'string' &&
36
+ (r.valueKind === undefined || r.valueKind === 'literal' || r.valueKind === 'regex'));
37
+ }
38
+ if (kind === 'group') {
39
+ // Structural, like `parent`: `matchGroupRule` reads `value` as text and
40
+ // `groupClass` as a class name, so neither may arrive as anything else.
41
+ const r = value;
42
+ return (CLASSIFICATION_OPS.has(r.op) &&
43
+ typeof r.value === 'string' &&
44
+ (r.groupClass === undefined || typeof r.groupClass === 'string') &&
45
+ (r.valueKind === undefined || r.valueKind === 'literal' || r.valueKind === 'regex'));
46
+ }
47
+ if ((kind === 'property' || kind === 'quantity') && !validReadOptions(value))
48
+ return false;
49
+ return (kind === 'model' ||
50
+ kind === 'storey' ||
51
+ kind === 'ifcType' ||
52
+ kind === 'predefinedType' ||
53
+ kind === 'name' ||
54
+ kind === 'globalId' ||
55
+ kind === 'attribute' ||
56
+ kind === 'property' ||
57
+ kind === 'quantity' ||
58
+ kind === 'material' ||
59
+ kind === 'classification' ||
60
+ kind === 'elevation' ||
61
+ kind === 'type');
62
+ }
63
+ /** `SubjectReadOptions` fields, when present, must hold a value the engine knows. */
64
+ function validReadOptions(value) {
65
+ const r = value;
66
+ return (r.valueUnit === undefined || r.valueUnit === 'si')
67
+ && (r.inherit === undefined || r.inherit === 'type' || r.inherit === 'aggregation');
68
+ }
69
+ export function parseFilterRules(raw) {
70
+ if (!Array.isArray(raw))
71
+ return [];
72
+ return raw.filter(isFilterRule);
73
+ }
74
+ //# sourceMappingURL=filter-rule-guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-rule-guards.js","sourceRoot":"","sources":["../../src/filter/filter-rule-guards.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Unified filter rule taxonomy.
3
+ *
4
+ * Ported from the Tauri-side `filter.rs` engine and consumed by the
5
+ * in-memory path-B runtime evaluator (`filter-evaluate.ts`). The
6
+ * discriminated-union shape lets the chip UI serialise any rule as a
7
+ * JSON object with a `"kind"` discriminator, mirroring serde's tagged
8
+ * enum encoding. We use `kind` rather than `type` because `type`
9
+ * collides with the IFC `type` attribute name on element rows.
10
+ */
11
+ import { type ModelTagOp } from './model-tag.js';
12
+ import { groupRule, type GroupRule } from './filter-group-rule.js';
13
+ import type { SubjectReadOptions } from './subject-read-options.js';
14
+ /** Set-membership: storey, ifcType, predefinedType. */
15
+ export type SetOp = 'in' | 'notIn';
16
+ /** String comparisons (Name rule). */
17
+ export type StringOp = 'eq' | 'ne' | 'contains' | 'notContains' | 'startsWith' | 'matches' | 'notMatches';
18
+ /** Numeric comparisons (Quantity rule). */
19
+ export type NumericOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte';
20
+ /** Mixed string+numeric+presence ops for Property values. */
21
+ export type ValueOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'contains' | 'notContains' | 'matches' | 'notMatches' | 'isSet' | 'isNotSet';
22
+ /** Classification value+presence ops. A classification is matched against
23
+ * its code / name string, so this is the StringOp comparison subset plus
24
+ * presence — numeric ops don't apply. */
25
+ export type ClassificationOp = 'eq' | 'ne' | 'contains' | 'notContains' | 'matches' | 'notMatches' | 'isSet' | 'isNotSet';
26
+ /** Top-level rule combinator. */
27
+ export type Combinator = 'AND' | 'OR';
28
+ /**
29
+ * How a rule reads one of its strings — the producer saying so, because the
30
+ * string itself cannot.
31
+ *
32
+ * `'regex'` is a regular-expression SOURCE: the WHOLE string is the pattern,
33
+ * slashes included. `'literal'` is exact text that is never a pattern, however
34
+ * it happens to be spelled. Absent means free text a human typed into a chip
35
+ * field, which keeps the Lists-panel convention (#1591): a `/body/flags`
36
+ * literal is a pattern, anything else is plain text.
37
+ *
38
+ * Guessing this back out of the text is the #4091 defect class — matched the
39
+ * wrong thing, said nothing — reappearing at the adapter seam. The selector
40
+ * grammar knows which it parsed: quoting is its ONLY escape hatch for a
41
+ * literal name, so `"/Wall/".FireRating` is the plain name `/Wall/`, and
42
+ * `Name=/\/tmp\//` is the source `/tmp/`. Sniffed for slashes, the first
43
+ * matches every `…Wall…` set and the second matches `tmp`.
44
+ *
45
+ * A property-set or property NAME has no operator beside it, so both kinds
46
+ * have to be declared. A VALUE's op already says whether it is a pattern, so
47
+ * only `'regex'` is ever recorded there.
48
+ */
49
+ export type TextKind = 'literal' | 'regex';
50
+ export interface StoreyRule {
51
+ kind: 'storey';
52
+ values: string[];
53
+ op: SetOp;
54
+ /**
55
+ * Optional exact storey identity, set only when the rule was mirrored
56
+ * from a HierarchyPanel click (which holds the real `(modelId,
57
+ * expressId)` of the storey the user selected). `IfcBuildingStorey.Name`
58
+ * is optional and not unique — two distinct storeys, even within one
59
+ * model, routinely share a Name (repeated "Level 1" across wings, or
60
+ * federated buildings). When `refs` is present, the evaluator matches
61
+ * an element's storey by this exact identity instead of by name, so
62
+ * clicking one storey never silently pulls in a same-named sibling.
63
+ * Undefined for manually authored/typed rules (the chip UI only offers
64
+ * names to type against), which keep matching by name as before.
65
+ */
66
+ refs?: ReadonlyArray<{
67
+ modelId: string;
68
+ expressId: number;
69
+ }>;
70
+ }
71
+ /** Match the loaded model that owns an element. Values use a durable source
72
+ * fingerprint so saved filters survive the fresh runtime ids minted on reload. */
73
+ export interface ModelRule {
74
+ kind: 'model';
75
+ values: string[];
76
+ op: SetOp;
77
+ }
78
+ /** Match the owning model by its user-facing MODEL TAGS (#4215). `tagIds` are ids
79
+ * (stable across renames); an id that no longer exists is unresolved → matches nothing. */
80
+ export interface ModelTagRule {
81
+ kind: 'modelTag';
82
+ op: ModelTagOp;
83
+ tagIds: string[];
84
+ }
85
+ export interface IfcTypeRule {
86
+ kind: 'ifcType';
87
+ values: string[];
88
+ op: SetOp;
89
+ /** Exact-class applicability, no subtype expansion (bSI #356, deferred by
90
+ * IDS to "Future 2.0+"). Default false/absent = today's behaviour
91
+ * (`values` already come pre-expanded through `expandTypes` at the
92
+ * chip/selector layer). Type-only here: the search evaluator
93
+ * (`filter-match.ts`) has no reason to read it, only the validation
94
+ * engine (#5138 PR 3) does. */
95
+ exactClass?: boolean;
96
+ }
97
+ export interface PredefinedTypeRule {
98
+ kind: 'predefinedType';
99
+ values: string[];
100
+ op: SetOp;
101
+ }
102
+ export interface NameRule {
103
+ kind: 'name';
104
+ op: StringOp;
105
+ value: string;
106
+ /** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
107
+ valueKind?: TextKind;
108
+ }
109
+ /** `325Q7Fhnf67OZC$$r43uzK` / `! 325Q7Fhnf67OZC$$r43uzK` — one element, by
110
+ * GlobalId. Multi-valued like `ifcType`/`storey` so several bare-GlobalId
111
+ * terms (or a Ctrl-click accumulation) fold into one rule; matching is
112
+ * case-SENSITIVE (`values` are 22-character base64 IFC GlobalIds, where
113
+ * case is significant), unlike every other set-membership rule here. */
114
+ export interface GlobalIdRule {
115
+ kind: 'globalId';
116
+ values: string[];
117
+ op: SetOp;
118
+ }
119
+ /**
120
+ * `Description=Foo`, `ObjectType != NULL`, … — an IFC attribute other than
121
+ * Name or PredefinedType, which each have their own rule kind. `name` is the
122
+ * schema attribute name (matched case-insensitively against what the source
123
+ * buffer's schema-driven extraction returns); a `GlobalId` name is rejected
124
+ * at the selector adapter rather than reaching here — `extractAllEntityAttributes`
125
+ * never surfaces it (it's a structural/display attribute the parser skips),
126
+ * so routing it here would silently match nothing instead of finding the
127
+ * element the bare-GlobalId term already exists to find.
128
+ */
129
+ export interface AttributeRule {
130
+ kind: 'attribute';
131
+ name: string;
132
+ op: ValueOp;
133
+ /** Raw user input. Numeric ops parse as f64; isSet/isNotSet ignore. */
134
+ value: string;
135
+ /** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
136
+ valueKind?: TextKind;
137
+ }
138
+ export interface PropertyRule extends SubjectReadOptions {
139
+ kind: 'property';
140
+ setName: string;
141
+ /** How `setName` reads — a regex set name is what lets one rule reach both
142
+ * `Pset_WallCommon` and `Pset_SlabCommon`. */
143
+ setNameKind?: TextKind;
144
+ propertyName: string;
145
+ /** How `propertyName` reads. */
146
+ propertyNameKind?: TextKind;
147
+ op: ValueOp;
148
+ /** Raw user input. Numeric ops parse as f64; isSet/isNotSet ignore. */
149
+ value: string;
150
+ /** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
151
+ valueKind?: TextKind;
152
+ }
153
+ export interface QuantityRule extends SubjectReadOptions {
154
+ kind: 'quantity';
155
+ setName: string;
156
+ /** How `setName` reads. */
157
+ setNameKind?: TextKind;
158
+ quantityName: string;
159
+ /** How `quantityName` reads. */
160
+ quantityNameKind?: TextKind;
161
+ op: NumericOp;
162
+ value: number;
163
+ }
164
+ /** Match against an element's material name(s) — top-level material,
165
+ * layer / constituent / profile names, list members — AND Category (#4094).
166
+ * Multi-valued: the evaluator matches if ANY candidate satisfies a positive
167
+ * op, or NONE violates a negative op (ne / notContains). */
168
+ export interface MaterialRule {
169
+ kind: 'material';
170
+ op: StringOp;
171
+ value: string;
172
+ /** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
173
+ valueKind?: TextKind;
174
+ }
175
+ /** Match against an element's classification references (e.g. Uniclass,
176
+ * OmniClass). `system` optionally scopes to one classification system;
177
+ * the value matches a reference's code (identification) OR name. */
178
+ export interface ClassificationRule {
179
+ kind: 'classification';
180
+ /** Optional system scope (e.g. "Uniclass 2015"). Empty = any system. */
181
+ system?: string;
182
+ op: ClassificationOp;
183
+ /** Matched against identification (code) OR name. Ignored for isSet/isNotSet. */
184
+ value: string;
185
+ /** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
186
+ valueKind?: TextKind;
187
+ }
188
+ /** Match against an element's elevation in metres — derived from the
189
+ * elevation of the building storey the element belongs to. */
190
+ export interface ElevationRule {
191
+ kind: 'elevation';
192
+ op: NumericOp;
193
+ /** Threshold in metres. */
194
+ value: number;
195
+ }
196
+ /**
197
+ * `type=WT01` (IfcOpenShell selector syntax) — match against the Name of
198
+ * the element's RELATING TYPE, reached via `IfcRelDefinesByType`. This is
199
+ * a different dimension from {@link IfcTypeRule}, which matches the
200
+ * element's own IFC *class* (`IfcWall`); `type=` instead matches the type
201
+ * OBJECT's `Name` attribute (e.g. `IfcWallType.Name`, "WT01"). An element
202
+ * with no `IfcRelDefinesByType` relation never matches. #4094.
203
+ */
204
+ export interface TypeNameRule {
205
+ kind: 'type';
206
+ op: StringOp;
207
+ value: string;
208
+ /** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
209
+ valueKind?: TextKind;
210
+ }
211
+ /** `parent=Foo` (#4903) — direct or indirect spatial-hierarchy child of an
212
+ * element named `Foo`; walks containment AND aggregation, any depth, via
213
+ * `@ifc-lite/data`'s shared `collectSpatialAncestors` (see
214
+ * `filter-match.ts`'s `matchParentRule`). Multi-valued like `material`:
215
+ * ANY ancestor Name matching a positive op, or NONE violating a negative
216
+ * one; no (matching) ancestors satisfies neither op — EMPTY, not "no filter". */
217
+ export interface ParentRule {
218
+ kind: 'parent';
219
+ op: StringOp;
220
+ value: string;
221
+ /** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
222
+ valueKind?: TextKind;
223
+ }
224
+ export type FilterRule = ModelRule | ModelTagRule | StoreyRule | IfcTypeRule | PredefinedTypeRule | NameRule | GlobalIdRule | AttributeRule | PropertyRule | QuantityRule | MaterialRule | ClassificationRule | ElevationRule | TypeNameRule | ParentRule | GroupRule;
225
+ /** Combine an array of per-rule booleans according to AND/OR semantics. */
226
+ export declare function combineRuleResults(combinator: Combinator, results: readonly boolean[]): boolean;
227
+ /** Dedupe-merge two `StoreyRule.refs` lists by (modelId, expressId), used
228
+ * when a Ctrl-click accumulates another storey into an existing filter
229
+ * (HierarchyPanel). */
230
+ export declare function mergeStoreyRefs(prior: ReadonlyArray<{
231
+ modelId: string;
232
+ expressId: number;
233
+ }>, next: ReadonlyArray<{
234
+ modelId: string;
235
+ expressId: number;
236
+ }>): Array<{
237
+ modelId: string;
238
+ expressId: number;
239
+ }>;
240
+ /** Add a HierarchyPanel storey click to its mirrored `op:in` rule.
241
+ *
242
+ * A rule created by the hierarchy carries exact refs. A manually authored
243
+ * rule has no refs and deliberately matches by its names; changing that rule
244
+ * to ref mode would discard every existing manual selection. Keep it in name
245
+ * mode when extending it, while hierarchy-originated rules retain exact refs.
246
+ */
247
+ export declare function addHierarchyStoreyToRule(prior: StoreyRule | undefined, name: string, refs: ReadonlyArray<{
248
+ modelId: string;
249
+ expressId: number;
250
+ }>): StoreyRule;
251
+ export declare const Rule: {
252
+ readonly model: (values: string[], op?: SetOp) => ModelRule;
253
+ readonly modelTag: (op: ModelTagOp, tagIds: string[]) => ModelTagRule;
254
+ readonly storey: (values: string[], op?: SetOp, refs?: ReadonlyArray<{
255
+ modelId: string;
256
+ expressId: number;
257
+ }>) => StoreyRule;
258
+ readonly ifcType: (values: string[], op?: SetOp) => IfcTypeRule;
259
+ readonly predefinedType: (values: string[], op?: SetOp) => PredefinedTypeRule;
260
+ readonly name: (op: StringOp, value: string, valueKind?: TextKind) => NameRule;
261
+ readonly globalId: (values: string[], op?: SetOp) => GlobalIdRule;
262
+ readonly attribute: (name: string, op: ValueOp, value: string, valueKind?: TextKind) => AttributeRule;
263
+ readonly property: (setName: string, propertyName: string, op: ValueOp, value: string, kinds?: Pick<PropertyRule, "setNameKind" | "propertyNameKind" | "valueKind">) => PropertyRule;
264
+ readonly quantity: (setName: string, quantityName: string, op: NumericOp, value: number, kinds?: Pick<QuantityRule, "setNameKind" | "quantityNameKind">) => QuantityRule;
265
+ readonly material: (op: StringOp, value: string, valueKind?: TextKind) => MaterialRule;
266
+ readonly classification: (system: string, op: ClassificationOp, value: string, valueKind?: TextKind) => ClassificationRule;
267
+ readonly elevation: (op: NumericOp, value: number) => ElevationRule;
268
+ readonly typeName: (op: StringOp, value: string, valueKind?: TextKind) => TypeNameRule;
269
+ readonly parent: (op: StringOp, value: string, valueKind?: TextKind) => ParentRule;
270
+ readonly group: typeof groupRule;
271
+ };
272
+ export { isFilterRule, parseFilterRules } from './filter-rule-guards.js';
273
+ export type { GroupRule } from './filter-group-rule.js';
274
+ export { activeGroupRules } from './filter-groups.js';
275
+ //# sourceMappingURL=filter-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-rules.d.ts","sourceRoot":"","sources":["../../src/filter/filter-rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { groupRule } from './filter-group-rule.js';
5
+ // ── Combinator helpers ────────────────────────────────────────────────────────
6
+ /** Combine an array of per-rule booleans according to AND/OR semantics. */
7
+ export function combineRuleResults(combinator, results) {
8
+ if (results.length === 0)
9
+ return false;
10
+ return combinator === 'AND' ? results.every((r) => r) : results.some((r) => r);
11
+ }
12
+ /** Dedupe-merge two `StoreyRule.refs` lists by (modelId, expressId), used
13
+ * when a Ctrl-click accumulates another storey into an existing filter
14
+ * (HierarchyPanel). */
15
+ export function mergeStoreyRefs(prior, next) {
16
+ const seen = new Set(prior.map((r) => `${r.modelId}:${r.expressId}`));
17
+ const merged = [...prior];
18
+ for (const r of next) {
19
+ const key = `${r.modelId}:${r.expressId}`;
20
+ if (!seen.has(key)) {
21
+ seen.add(key);
22
+ merged.push(r);
23
+ }
24
+ }
25
+ return merged;
26
+ }
27
+ /** Add a HierarchyPanel storey click to its mirrored `op:in` rule.
28
+ *
29
+ * A rule created by the hierarchy carries exact refs. A manually authored
30
+ * rule has no refs and deliberately matches by its names; changing that rule
31
+ * to ref mode would discard every existing manual selection. Keep it in name
32
+ * mode when extending it, while hierarchy-originated rules retain exact refs.
33
+ */
34
+ export function addHierarchyStoreyToRule(prior, name, refs) {
35
+ const values = Array.from(new Set([...(prior?.values ?? []), name]));
36
+ if (prior && !prior.refs)
37
+ return Rule.storey(values, 'in');
38
+ return Rule.storey(values, 'in', mergeStoreyRefs(prior?.refs ?? [], refs));
39
+ }
40
+ // ── Convenience constructors ──────────────────────────────────────────────────
41
+ //
42
+ // The chip UI builds rules via `set*` slice actions (see searchSlice.ts);
43
+ // these helpers exist primarily for tests and for code paths that synthesize
44
+ // rules from a different representation (URL state, presets).
45
+ export const Rule = {
46
+ model: (values, op = 'in') => ({ kind: 'model', values, op }),
47
+ modelTag: (op, tagIds) => ({ kind: 'modelTag', op, tagIds }),
48
+ storey: (values, op = 'in', refs) => ({ kind: 'storey', values, op, ...(refs ? { refs } : {}) }),
49
+ ifcType: (values, op = 'in') => ({ kind: 'ifcType', values, op }),
50
+ predefinedType: (values, op = 'in') => ({ kind: 'predefinedType', values, op }),
51
+ name: (op, value, valueKind) => ({ kind: 'name', op, value, ...(valueKind ? { valueKind } : {}) }),
52
+ globalId: (values, op = 'in') => ({ kind: 'globalId', values, op }),
53
+ attribute: (name, op, value, valueKind) => ({ kind: 'attribute', name, op, value, ...(valueKind ? { valueKind } : {}) }),
54
+ property: (setName, propertyName, op, value, kinds = {}) => ({ kind: 'property', setName, propertyName, op, value, ...kinds }),
55
+ quantity: (setName, quantityName, op, value, kinds = {}) => ({ kind: 'quantity', setName, quantityName, op, value, ...kinds }),
56
+ material: (op, value, valueKind) => ({ kind: 'material', op, value, ...(valueKind ? { valueKind } : {}) }),
57
+ classification: (system, op, value, valueKind) => ({ kind: 'classification', system: system || undefined, op, value, ...(valueKind ? { valueKind } : {}) }),
58
+ elevation: (op, value) => ({ kind: 'elevation', op, value }),
59
+ typeName: (op, value, valueKind) => ({ kind: 'type', op, value, ...(valueKind ? { valueKind } : {}) }),
60
+ parent: (op, value, valueKind) => ({ kind: 'parent', op, value, ...(valueKind ? { valueKind } : {}) }),
61
+ group: groupRule,
62
+ };
63
+ // ── JSON guards (`filter-rule-guards.ts`, re-exported for existing imports) ─
64
+ export { isFilterRule, parseFilterRules } from './filter-rule-guards.js';
65
+ // Re-exported so existing `from './filter-rules.js'` imports (HierarchyPanel,
66
+ // etc.) can pull in the groups helper too without a second import line (#4904).
67
+ export { activeGroupRules } from './filter-groups.js';
68
+ //# sourceMappingURL=filter-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-rules.js","sourceRoot":"","sources":["../../src/filter/filter-rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { MaterialInfo } from '@ifc-lite/parser';
2
+ /**
3
+ * Collect the distinct *individual* material names for an element from its
4
+ * resolved {@link MaterialInfo} — each layer / constituent / profile / list
5
+ * material. Deliberately excludes the layer-set / usage name (`info.name`,
6
+ * which for Revit exports is the family+type, not a material) UNLESS the
7
+ * element has no sub-structure, in which case the top-level name IS the single
8
+ * material. Order-preserving and de-duplicated, so a wall layered
9
+ * gypsumboard / insulation / gypsumboard yields `["gypsumboard", "insulation"]`
10
+ * and the element can be grouped/selected under each material. (#1366)
11
+ */
12
+ export declare function lensMaterialNames(info: MaterialInfo | null | undefined): string[];
13
+ //# sourceMappingURL=lens-material-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lens-material-names.d.ts","sourceRoot":"","sources":["../../src/filter/lens-material-names.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAcjF"}
@@ -0,0 +1,36 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Collect the distinct *individual* material names for an element from its
6
+ * resolved {@link MaterialInfo} — each layer / constituent / profile / list
7
+ * material. Deliberately excludes the layer-set / usage name (`info.name`,
8
+ * which for Revit exports is the family+type, not a material) UNLESS the
9
+ * element has no sub-structure, in which case the top-level name IS the single
10
+ * material. Order-preserving and de-duplicated, so a wall layered
11
+ * gypsumboard / insulation / gypsumboard yields `["gypsumboard", "insulation"]`
12
+ * and the element can be grouped/selected under each material. (#1366)
13
+ */
14
+ export function lensMaterialNames(info) {
15
+ if (!info)
16
+ return [];
17
+ const seen = new Set();
18
+ const add = (s) => {
19
+ const t = s?.trim();
20
+ if (t)
21
+ seen.add(t);
22
+ };
23
+ for (const l of info.layers ?? [])
24
+ add(l.materialName);
25
+ for (const c of info.constituents ?? [])
26
+ add(c.materialName);
27
+ for (const p of info.profiles ?? [])
28
+ add(p.materialName);
29
+ for (const m of info.materials ?? [])
30
+ add(m.name);
31
+ // No sub-structure → the element carries a single plain material.
32
+ if (seen.size === 0)
33
+ add(info.name);
34
+ return [...seen];
35
+ }
36
+ //# sourceMappingURL=lens-material-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lens-material-names.js","sourceRoot":"","sources":["../../src/filter/lens-material-names.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAI/D;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAqC;IACrE,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAG,CAAC,CAAU,EAAE,EAAE;QACzB,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC;QACpB,IAAI,CAAC;YAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACvD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,YAAY,IAAI,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAC7D,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACzD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,IAAI,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAClD,kEAAkE;IAClE,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AACnB,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The project-unit lookups `readSubject` needs to say what unit a property
3
+ * or quantity value is recorded in (#5300) and what factor turns it into SI
4
+ * (#5225). One memoised `ProjectUnits` per store, from the same
5
+ * `extractProjectUnits` resolver that backs unit display and the IDS
6
+ * bridge's scaling.
7
+ */
8
+ import { type IfcDataStore, type ProjectUnits } from '@ifc-lite/parser';
9
+ import { QuantityType } from '@ifc-lite/data';
10
+ /** `store`'s project units, or `null` when the store has no source to read them from. */
11
+ export declare function projectUnitsOf(store: IfcDataStore): ProjectUnits | null;
12
+ export declare const QUANTITY_MEASURE_TYPE: Partial<Record<QuantityType, string>>;
13
+ /** The project's display unit for IFC measure type `measureType`, if any. */
14
+ export declare function projectUnitSymbol(store: IfcDataStore, measureType: string | undefined): string | undefined;
15
+ /**
16
+ * SI factor of a value of IFC measure type `measureType` recorded in the
17
+ * project's units, or `undefined` when the type has no unit (a label, a
18
+ * count, a ratio). Area and volume use the project's declared AREAUNIT /
19
+ * VOLUMEUNIT and fall back to the length unit squared / cubed, the rule
20
+ * `quantitySiScale` and the IDS bridge already apply.
21
+ */
22
+ export declare function projectSiScale(store: IfcDataStore, measureType: string | undefined): number | undefined;
23
+ /** SI factor of one collected quantity: its explicit `Unit`, else the project unit for its type. */
24
+ export declare function quantityValueSiScale(store: IfcDataStore, quantity: {
25
+ type: number;
26
+ value: number;
27
+ explicitUnitSiScale?: number;
28
+ }): number | undefined;
29
+ //# sourceMappingURL=measure-units.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measure-units.d.ts","sourceRoot":"","sources":["../../src/filter/measure-units.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,IAAI,CAOvE;AAED,eAAO,MAAM,qBAAqB,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAMvE,CAAC;AAEF,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAG1G;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CASvG;AAED,oGAAoG;AACpG,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAE,GACtE,MAAM,GAAG,SAAS,CAUpB"}
@@ -0,0 +1,72 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * The project-unit lookups `readSubject` needs to say what unit a property
6
+ * or quantity value is recorded in (#5300) and what factor turns it into SI
7
+ * (#5225). One memoised `ProjectUnits` per store, from the same
8
+ * `extractProjectUnits` resolver that backs unit display and the IDS
9
+ * bridge's scaling.
10
+ */
11
+ import { extractProjectUnits, quantitySiScale, } from '@ifc-lite/parser';
12
+ import { QuantityType } from '@ifc-lite/data';
13
+ const projectUnitsCache = new WeakMap();
14
+ /** `store`'s project units, or `null` when the store has no source to read them from. */
15
+ export function projectUnitsOf(store) {
16
+ let units = projectUnitsCache.get(store);
17
+ if (units === undefined) {
18
+ units = store.source?.length && store.entityIndex ? extractProjectUnits(store.source, store.entityIndex) : null;
19
+ projectUnitsCache.set(store, units);
20
+ }
21
+ return units;
22
+ }
23
+ export const QUANTITY_MEASURE_TYPE = {
24
+ [QuantityType.Length]: 'IfcLengthMeasure',
25
+ [QuantityType.Area]: 'IfcAreaMeasure',
26
+ [QuantityType.Volume]: 'IfcVolumeMeasure',
27
+ [QuantityType.Weight]: 'IfcMassMeasure',
28
+ [QuantityType.Time]: 'IfcTimeMeasure',
29
+ };
30
+ /** The project's display unit for IFC measure type `measureType`, if any. */
31
+ export function projectUnitSymbol(store, measureType) {
32
+ if (!measureType)
33
+ return undefined;
34
+ return projectUnitsOf(store)?.unitForMeasure(measureType)?.symbol;
35
+ }
36
+ /**
37
+ * SI factor of a value of IFC measure type `measureType` recorded in the
38
+ * project's units, or `undefined` when the type has no unit (a label, a
39
+ * count, a ratio). Area and volume use the project's declared AREAUNIT /
40
+ * VOLUMEUNIT and fall back to the length unit squared / cubed, the rule
41
+ * `quantitySiScale` and the IDS bridge already apply.
42
+ */
43
+ export function projectSiScale(store, measureType) {
44
+ if (!measureType)
45
+ return undefined;
46
+ const units = projectUnitsOf(store);
47
+ if (!units)
48
+ return undefined;
49
+ const upper = measureType.toUpperCase();
50
+ const length = () => units.unitForMeasure('IfcLengthMeasure')?.siScale ?? 1;
51
+ if (upper === 'IFCAREAMEASURE')
52
+ return units.resolvedForUnitType('AREAUNIT')?.siScale ?? length() ** 2;
53
+ if (upper === 'IFCVOLUMEMEASURE')
54
+ return units.resolvedForUnitType('VOLUMEUNIT')?.siScale ?? length() ** 3;
55
+ return units.unitForMeasure(measureType)?.siScale;
56
+ }
57
+ /** SI factor of one collected quantity: its explicit `Unit`, else the project unit for its type. */
58
+ export function quantityValueSiScale(store, quantity) {
59
+ if (quantity.explicitUnitSiScale !== undefined)
60
+ return quantity.explicitUnitSiScale;
61
+ const measureType = QUANTITY_MEASURE_TYPE[quantity.type];
62
+ if (!measureType)
63
+ return undefined;
64
+ const units = projectUnitsOf(store);
65
+ if (!units)
66
+ return undefined;
67
+ if (quantity.type === QuantityType.Length || quantity.type === QuantityType.Area || quantity.type === QuantityType.Volume) {
68
+ return quantitySiScale({ name: '', ...quantity }, units);
69
+ }
70
+ return projectSiScale(store, measureType);
71
+ }
72
+ //# sourceMappingURL=measure-units.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measure-units.js","sourceRoot":"","sources":["../../src/filter/measure-units.ts"],"names":[],"mappings":"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"}