@faqir-ui/core 1.0.0 → 1.1.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 (41) hide show
  1. package/README.md +45 -5
  2. package/cdn.json +38 -22
  3. package/dist/faqir-core.js +89 -52
  4. package/dist/faqir-core.min.js +3 -3
  5. package/dist/faqir-core.min.js.map +3 -3
  6. package/dist/faqir-core.mjs +61 -54
  7. package/dist/faqir.aurora.css +1209 -507
  8. package/dist/faqir.brutalist.css +1184 -489
  9. package/dist/faqir.candy.css +14152 -0
  10. package/dist/faqir.clinical.css +14152 -0
  11. package/dist/faqir.contrast.css +1198 -526
  12. package/dist/faqir.default.css +1261 -588
  13. package/dist/faqir.document-serif.css +1211 -491
  14. package/dist/faqir.document.css +1193 -490
  15. package/dist/faqir.editorial-document.css +14116 -0
  16. package/dist/faqir.editorial.css +14152 -0
  17. package/dist/faqir.fintech.css +14152 -0
  18. package/dist/faqir.glass.css +1214 -517
  19. package/dist/faqir.ink-document.css +14116 -0
  20. package/dist/faqir.ink.css +14127 -0
  21. package/dist/faqir.luxe.css +14211 -0
  22. package/dist/faqir.midnight.css +1229 -507
  23. package/dist/faqir.neo.css +14153 -0
  24. package/dist/faqir.neumorph.css +14151 -0
  25. package/dist/faqir.nordic.css +14151 -0
  26. package/dist/faqir.organic.css +14152 -0
  27. package/dist/faqir.paper.css +1200 -508
  28. package/dist/faqir.slate.css +1296 -564
  29. package/dist/faqir.soft.css +1180 -494
  30. package/dist/faqir.sunset.css +14153 -0
  31. package/dist/faqir.swiss-document.css +14116 -0
  32. package/dist/faqir.swiss.css +14153 -0
  33. package/dist/faqir.terminal.css +1187 -491
  34. package/dist/plugins/faqir-collapse.js +1 -1
  35. package/dist/plugins/faqir-intersect.js +2 -0
  36. package/dist/plugins/faqir-mask.js +27 -17
  37. package/dist/plugins/faqir-rules.js +63 -0
  38. package/dist/plugins/faqir-validate.js +471 -58
  39. package/dist/sri.json +36 -20
  40. package/faqir-core.d.ts +111 -5
  41. package/package.json +1 -1
package/dist/sri.json CHANGED
@@ -1,23 +1,39 @@
1
1
  {
2
- "faqir-core.js": "sha384-vH2gsWr7R/OAJLvYeBC4txN6mleQzdRiuLsc5AH2xbdge5+zQipF5AqSJS7Yc4Vz",
3
- "faqir-core.min.js": "sha384-BHt1gSursbCylX/U3FT6iW5dWukyZcjDXKWOanw4baYgwn8qj1LIpI1It8ct7CyK",
4
- "faqir-core.min.js.map": "sha384-io5FkzZ1meZXs3UY/kEJkmvB8YXwO/JfezQe4yZop6KZZjjwn6UCjeDUSh0FG1sz",
5
- "faqir-core.mjs": "sha384-jqsZ/HqqXSuUjt6SikvDjynm7EdDVAfVLXYSoJHjzvOF+3V5CDmEZgzXDJPWvQ4I",
6
- "faqir.aurora.css": "sha384-M7yDwTC7MuWfGfiIFLv9MFibCkYDDSHx6RFszEQ7iyd4Lp/bEG/SIyRcvSsfn2Vv",
7
- "faqir.brutalist.css": "sha384-aRtTqpJetmoMa6uL2krMPEHsjTwF11oNlTzS9zZrdtqXSvzkSUCKKoHyr1WbCBnb",
8
- "faqir.contrast.css": "sha384-Fy3tZU7cwb7LGNm9B/5nFNK1yRgwAZqv+FF69pY/w6AEGykZA4jSoDeFKU4hXdBf",
9
- "faqir.default.css": "sha384-w2sH1K7AwYMeLQIhxBnAU1LuRrexg/xJx/eLLMgAjG7avxLYhYeuvM2pTu1yJJVi",
10
- "faqir.document-serif.css": "sha384-2xWhB1DahXndhbbk7D+RV6w1NI7lPoO3tPgVtDvgWp8G+qE4jjI5nCWZa0IC1XiV",
11
- "faqir.document.css": "sha384-loA3uWvclgLBd8OntpB4YrQP/jBsLScb06KI61EMauFjYxOadmCszUBkYYNoo4Wc",
12
- "faqir.glass.css": "sha384-OQOzZy8BxLxPl1pFNkCwizX0oqOsmPf49FKhFa4d9HUM6bcJrJnzw3XU8IZGqSkG",
13
- "faqir.midnight.css": "sha384-J0SQyAklYwD+yJ7jubtIJ+0t9DWBymcJikhI242PpTvzAL9SU4iWTYCwJBqSUbj0",
14
- "faqir.paper.css": "sha384-OCmkztWvVBgacdb9HlGiRl+RRQ1QaFU8MCrQIYLeL17EMsT2tG8lZeU0mfQKLo6N",
15
- "faqir.slate.css": "sha384-BxHSyxsLdi690Q1LBWIyAXodugjLNT764ZjqBRAaCtAaQeei81qzV46C5rMYonb4",
16
- "faqir.soft.css": "sha384-a77S0Tcfd1I2V+r6Prt4gTtIzSZahltCuQ0jEzOKXUd+taDRjM0EsIy3n5VycLJT",
17
- "faqir.terminal.css": "sha384-YvP4CkNUhcsFYJjBgnhcSMthsEheRg2RlZ0837GBzDVfmeJx9IYpMSrG7BkAb697",
18
- "plugins/faqir-collapse.js": "sha384-y16PnFkcJiJLQIxuQMtdS+QalrC6lJ0EsPT/oceZWpLMGdqASXq3HhVHebfUWktm",
19
- "plugins/faqir-intersect.js": "sha384-AfbB6icyS1ngl1JdiAMZ9//m5lHTMdgXXHWCdi5INfE9FmLbYRUeiyKTv4E4g6ri",
20
- "plugins/faqir-mask.js": "sha384-cSq2DpUnoJCxEDAQjsbzAa+jSuHf4WsOaKT8t7b9p8pA7MaaRhA1DLzjMNChSa/I",
2
+ "faqir-core.js": "sha384-Ehw+8Knrsxpt9enram44fdKrZh9cJoKDO8WeN7+gZ4DDJEH/RwHiceK7lgfiGprw",
3
+ "faqir-core.min.js": "sha384-+FqfiMSc4+AeDam5DHWdByfqFpegDaGaYGsKVFeKqrV2YHahZla6egt04qPvvHSc",
4
+ "faqir-core.min.js.map": "sha384-eMfL8gnKtbSNBDSDa8FvuTsbIe5QFjcgaMktueIfzLSGL48HzFBmCA6Wt4mMKapj",
5
+ "faqir-core.mjs": "sha384-GIAWwY5wDRhwHb3/yKRvQ7D8oSmMI4PZKI0IsSMye5K1mnIwtCbgG20zphtOCn2x",
6
+ "faqir.aurora.css": "sha384-TrPBHGXGxwY6sLypt3kbjbhEHz87wsYgqQhzPqi5zghmsiqewgykQx6aS+WP2O0h",
7
+ "faqir.brutalist.css": "sha384-N/VfEAEdOZ2PGFX4xsPzlHEmDkXtjzmkXXW1Ta3PCtBV/RZm1rF4EYsfwLEvwqPZ",
8
+ "faqir.candy.css": "sha384-/lk9HAr46O2pYwsM8vE8MBVkPLB1t2otA3Edfux98b564DvNkWqpsD4DSVdcmHAX",
9
+ "faqir.clinical.css": "sha384-quTFS0lcUB0sz5ysan8vVX75oBDNzY+of7CmKDEoX5fM5OCIbYEttiZ8eLL/vQ4u",
10
+ "faqir.contrast.css": "sha384-Kkc5S9mDWhATTvHHfZhNd+rN06hSCvbKLuqa5y+cwtvlF7jSunMH1bLkfrZsVw5f",
11
+ "faqir.default.css": "sha384-bbc2p6aV7UYxrmv8M6x0buppf4uT7yh8DZ9d///ykZjXQokcZNtOk6xK1UUl6Mnj",
12
+ "faqir.document-serif.css": "sha384-gruBhX1KhlPRKzCVMODRBoOB+IpJM3lgYB+xQgCbu35onXyy+OFvh0MBDThrRFSq",
13
+ "faqir.document.css": "sha384-oC4VnHJi2ez8nAPSBwN4GWOz+BraAWcXXcGjNrQmdKujuA3fVmawKwolH1zIEzT0",
14
+ "faqir.editorial-document.css": "sha384-sKWLbBQ4IvgSvhLYo0nE95l6pqku+T0VTmkkoTwg/YOx5vM9gBAPA7f6CLE8gLNa",
15
+ "faqir.editorial.css": "sha384-N5sYSpAAOB81nDI+eShZ+gTZ5zbTMwaUt9fIPxwiNWBkKdaEJnsvyP3na/2SyNbv",
16
+ "faqir.fintech.css": "sha384-xY6baIhCB0boozwIAPzhPg2FFZ8RhqSf/13CWeda9Bd+9D5bvZbNuiFcO67GGLOL",
17
+ "faqir.glass.css": "sha384-MW9qUMfNSCgUyQjY/UqCpRxsXxuDEoVFvvpLy2htmV1Vc2mtn/z7uCXscj6Yn5zq",
18
+ "faqir.ink-document.css": "sha384-uWhbYEZwSDk3QHPMWe7lzYM0HELolHkW8xyqoowVvXrToqTXnSYVw7zTVET3kTVC",
19
+ "faqir.ink.css": "sha384-57zpUenZ+vVG/PViYuf1yxB0VxdV/5hxhZbKy9vi8XawKTMpbbU7AtnvgZ81ZIvs",
20
+ "faqir.luxe.css": "sha384-AP+OFzUaZ0RNEOGS95dsf09tD8ltts0VslqgCyaJ3CBHHkesKJ+/MT3SA4gZPxbe",
21
+ "faqir.midnight.css": "sha384-xsSMTT7Pf9i0CDFfx5hlzCBkHx5gsfORYS3rZuKnasgMkHumNUsy0fTBFcHBxSo3",
22
+ "faqir.neo.css": "sha384-rNHNMTeReWOmjhAayIam2CSmH3cUpHI3VbCOxg1hhk0GE3pAB2GX6tqzXH8OU9kX",
23
+ "faqir.neumorph.css": "sha384-7N6RHoYWSlnTHeTwVWrCn4ey1KR62fsAS0p1QVyb0gcljIYhcMWADZrmH/hOjhx+",
24
+ "faqir.nordic.css": "sha384-A/O40XHz2mMUs3tKWT7usnwgAxSsdFpb8uXKNMtoIa3OBaR2Ibpqg5mGNov90PaT",
25
+ "faqir.organic.css": "sha384-acTW5ka4Zy5SXHHn1My078WAnPkj6/KbLHKuWzToArB8rWlwZGRqlFxfq8VNAaqY",
26
+ "faqir.paper.css": "sha384-O26GS1gp6lFBZmollq/g21aUGVoWixAfBEsFxhWzPif1X2ZrjeXyIOEmCn25R1Dz",
27
+ "faqir.slate.css": "sha384-lSeSUhJCMUsQxM1oS2AbeqbfdLzquz4zYDYSF1N2bpA4JC0g/7fcJA/lWvkZugyq",
28
+ "faqir.soft.css": "sha384-G7xaO/Rr9RdMdBch66kUiS+atQOluVXhwIb039G7WJg6KvAxDBSbA/7v8y9ouhZH",
29
+ "faqir.sunset.css": "sha384-7FyjK1RJrkGTvOSFLH15WiRI1i8V3bbfpUuv4Gq3stG1NwC56/JkXOH4uPscY95b",
30
+ "faqir.swiss-document.css": "sha384-hQKtiQvaCu9ot5TJnCIlPjZhUJif5cacuE27IvJi1j99iF9HuNOvfGp+epSzJlMT",
31
+ "faqir.swiss.css": "sha384-Ki39mfAWeHD1KRjAB07b4MygOk5swzXSp5sUKcTWldXuiNhpNTWo+vOeponF4yfB",
32
+ "faqir.terminal.css": "sha384-EE2EAqi6sG4GTe8l+7w0p8gqCjZu8A+dkfNFCx90Ue/loSNUSnLIYDqdAsApyOOR",
33
+ "plugins/faqir-collapse.js": "sha384-3l5Z+isXlDkidRevDGkuNOiDp6eJ2ML11RkXA0j4ixQBaepuu8pAhyY4YRnR1qB7",
34
+ "plugins/faqir-intersect.js": "sha384-Q/akZjAcnTnGYPKBP7b8c3iyYbHTIW1IPjBivzOH9dE7Nflr9Cu6adjeDXU2bhk6",
35
+ "plugins/faqir-mask.js": "sha384-7yA/VdjGdg/6vwX+zUbughO6ERyV2rEsVyNYBO5ghqJbAhj9912F9qMPTkLc55B6",
21
36
  "plugins/faqir-persist.js": "sha384-o0jfddebC8QZ3S26VXUlOme723BNMlb/N7vqpn+fWpSeEFXzpq+3MoeXhVL/0PSv",
22
- "plugins/faqir-validate.js": "sha384-DSzQ7I94Qm+VKjpgBo3qgALyuU3zgQZ+jXOIqgRHkJ6utr8nqF7tQMKWnOv1/YH2"
37
+ "plugins/faqir-rules.js": "sha384-xE90r5W3AlWKu+idcwx6NAkVUcRWMgM9ZJ1VgJLOguj/0GYP0jfflCojiCWt4FVq",
38
+ "plugins/faqir-validate.js": "sha384-TIyGNL8dHBnFdV56LAhdklvhQLsClQqGuQ7DT0Zgxva8DIzfONXZSJYTXhQxJcN0"
23
39
  }
package/faqir-core.d.ts CHANGED
@@ -137,9 +137,95 @@ export interface Magics {
137
137
  * The interfaces are module-level exports, so an augmentation names one
138
138
  * directly — there is no `namespace Faqir` wrapper to reach through. The same
139
139
  * form opens {@link ControllerApis} and {@link Stores}.
140
+ *
141
+ * A magic whose SHAPE is fixed by the plugin gets its shape declared here even
142
+ * though the property is not: `plugins/faqir-rules.js` registers `$rules`, and
143
+ * {@link RulesState} is what it answers, so the augmentation is one line rather
144
+ * than a re-description —
145
+ *
146
+ * declare module "@faqir-ui/core" {
147
+ * interface PluginMagics { $rules: RulesState }
148
+ * }
140
149
  */
141
150
  export interface PluginMagics {}
142
151
 
152
+ /**
153
+ * What `$rules` answers — the live verdict of the `l-rules` definition bound to
154
+ * the form in this scope, installed by `plugins/faqir-rules.js`. [1.1B-07]
155
+ *
156
+ * Reactive, so an expression that reads it re-runs when the form changes; and
157
+ * never undefined — a scope with no rules form gets the same shape with every
158
+ * map empty, so `$rules.next[step]` is safe to read anywhere.
159
+ *
160
+ * The keys of `visible`, `required` and `computed` are field paths as the
161
+ * definition spells them (`"seats"`, `"address.city"`); `next` is keyed by the
162
+ * page a `jump` rule fires ON and valued with the page it sends the form to, so
163
+ * a wizard reads `$rules.next[currentPage]` instead of counting by one.
164
+ */
165
+ export interface RulesState {
166
+ /** path → whether a `show` rule leaves the field on screen. */
167
+ readonly visible: Readonly<Record<string, boolean>>;
168
+ /** path → whether a `require` rule makes the field mandatory right now. */
169
+ readonly required: Readonly<Record<string, boolean>>;
170
+ /** path → the value its `compute` rule derived. */
171
+ readonly computed: Readonly<Record<string, unknown>>;
172
+ /** from-page → to-page, for every `jump` rule whose `when` currently holds. */
173
+ readonly next: Readonly<Record<string, string>>;
174
+ }
175
+
176
+ /** What one programmatic validator answers: pass, fail, or a message. */
177
+ export type ValidatorResult = boolean | string;
178
+
179
+ /** The second argument every registered validator receives. */
180
+ export interface ValidatorContext {
181
+ /** The control being validated. */
182
+ el: Element;
183
+ /** The form it was registered against. */
184
+ form: Element;
185
+ /** The form's `l-data` scope, or null when the form carries no `l-validate`. */
186
+ data: Scope | null;
187
+ }
188
+
189
+ /**
190
+ * A programmatic validator. Return `true` to pass, `false` to fail with the
191
+ * registered message, or a string to fail with that message — or a promise of
192
+ * any of those, which puts the field-group in `data-state="validating"` until
193
+ * it settles. Throwing or rejecting is a failure with a built-in message.
194
+ */
195
+ export type FieldValidator = (
196
+ value: string | null,
197
+ ctx: ValidatorContext,
198
+ ) => ValidatorResult | Promise<ValidatorResult>;
199
+
200
+ /**
201
+ * `Faqir.validate` — installed by `plugins/faqir-validate.js`, which is why the
202
+ * member is optional on {@link FaqirGlobal}. A page that does not load the
203
+ * plugin does not have it. [1.1B-03]
204
+ */
205
+ export interface ValidateApi {
206
+ /**
207
+ * Add a named validator to the control(s) named `field` in `form` (an element
208
+ * or a selector). Registered validators run after native constraints and
209
+ * after the `l-validate:<name>` attribute validators, in registration order,
210
+ * first failure wins. Returns a function that removes this one again.
211
+ */
212
+ register(
213
+ form: Element | string,
214
+ field: string,
215
+ name: string,
216
+ fn: FieldValidator,
217
+ message?: string,
218
+ ): Disposer;
219
+ /** Remove one named validator — or, with no `name`, all of the field's. */
220
+ unregister(form: Element | string, field: string, name?: string): void;
221
+ /**
222
+ * Validate every control of `form` and resolve to whether it is clean.
223
+ * Flushes any pending debounce, waits for every async check, and turns live
224
+ * revalidation on the way a submit attempt does.
225
+ */
226
+ run(form: Element | string): Promise<boolean>;
227
+ }
228
+
143
229
  /**
144
230
  * A live reactive scope: the `l-data` object, the `data-prop-*` values merged
145
231
  * over it, whatever `l-source` injected, and the magics on its prototype.
@@ -652,11 +738,11 @@ export interface DevtoolsComponent {
652
738
 
653
739
  /**
654
740
  * One recorded diagnostic. The production engine records none, so
655
- * `warnings()` is always `[]` there — the four classes exist only in
656
- * `faqir-core.dev.js`.
741
+ * `warnings()` is always `[]` there — every class exists only in
742
+ * `faqir-core.dev.js`. `key` is a duplicate `l-key` in a keyed `l-for`.
657
743
  */
658
744
  export interface DevtoolsWarning {
659
- kind: "expression" | "directive" | "reorder" | "html";
745
+ kind: "expression" | "directive" | "reorder" | "key" | "html" | "plugin";
660
746
  message: string;
661
747
  /** The offending element, as a short label. */
662
748
  element: string | null;
@@ -687,6 +773,14 @@ export interface Devtools {
687
773
  stores(): Record<string, Record<string, unknown>>;
688
774
  /** Diagnostics recorded so far, oldest first. */
689
775
  warnings(): DevtoolsWarning[];
776
+ /**
777
+ * Record one diagnostic on a plugin's behalf — the seam a plugin file uses to
778
+ * be as loud in the dev build as the engine is, having no reach into the
779
+ * engine's own hooks. `true` when it was recorded, `false` in the production
780
+ * build (which records nothing) and for a repeat the dev build has already
781
+ * printed. [1.1B-03]
782
+ */
783
+ report(message: string, el?: Element | null): boolean;
690
784
  }
691
785
 
692
786
  // ─────────────────────────────────────────────────────────────────────────
@@ -777,6 +871,16 @@ export interface FaqirGlobal {
777
871
  * than whichever engine touched the global last.
778
872
  */
779
873
  readonly devtools: Devtools;
874
+
875
+ // ── Plugin-installed ──
876
+ /**
877
+ * The programmatic validation surface `plugins/faqir-validate.js` installs.
878
+ * Optional because it is a plugin's, not the engine's: on a page that never
879
+ * loads the file it is simply absent, so reach it as `Faqir.validate?.run(f)`.
880
+ * The reflective drift test knows an optional member here may be missing from
881
+ * the engine for exactly this reason. [1.1B-03]
882
+ */
883
+ readonly validate?: ValidateApi;
780
884
  }
781
885
 
782
886
  declare const Faqir: FaqirGlobal;
@@ -797,7 +901,8 @@ declare namespace Faqir {
797
901
  TableSort, TableState, TableApi, TabsApi, TagInputApi, ToastApi,
798
902
  ToggleGroupApi, TooltipApi, TreeViewApi, ControllerApis, ProtocolState,
799
903
  Inspection, DevtoolsScope, DevtoolsComponent, DevtoolsWarning, Devtools,
800
- FaqirGlobal };
904
+ ValidatorResult, ValidatorContext, FieldValidator, ValidateApi,
905
+ RulesState, FaqirGlobal };
801
906
  }
802
907
 
803
908
  export default Faqir;
@@ -845,7 +950,8 @@ declare global {
845
950
  SidebarApi, SliderApi, TableSort, TableState, TableApi, TabsApi,
846
951
  TagInputApi, ToastApi, ToggleGroupApi, TooltipApi, TreeViewApi,
847
952
  ControllerApis, ProtocolState, Inspection, DevtoolsScope,
848
- DevtoolsComponent, DevtoolsWarning, Devtools, FaqirGlobal };
953
+ DevtoolsComponent, DevtoolsWarning, Devtools, ValidatorResult,
954
+ ValidatorContext, FieldValidator, ValidateApi, RulesState, FaqirGlobal };
849
955
  }
850
956
  interface Window {
851
957
  /** Set by the classic-script build; absent under a bundler import. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faqir-ui/core",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Faqir UI runtime engine — the Alpine-style reactive core (faqir-core.js), minified CDN build, and prebuilt per-theme CSS bundles. Zero dependencies.",
5
5
  "type": "module",
6
6
  "main": "./dist/faqir-core.mjs",