@jxsuite/runtime 4.1.0 → 5.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jxsuite/runtime",
3
- "version": "4.1.0",
3
+ "version": "5.2.0",
4
4
  "description": "JSON-native reactive web component runtime",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -33,10 +33,11 @@
33
33
  "upgrade": "bun update --latest && bun install"
34
34
  },
35
35
  "dependencies": {
36
- "@jxsuite/schema": "^3.0.0",
37
- "@vue/reactivity": "3.5.43"
36
+ "@jxsuite/schema": "^4.0.0",
37
+ "@vue/reactivity": "3.5.44"
38
38
  },
39
39
  "devDependencies": {
40
- "@happy-dom/global-registrator": "^20.14.6"
40
+ "@happy-dom/global-registrator": "^21.0.4",
41
+ "@jxsuite/test-support": "^0.0.0"
41
42
  }
42
43
  }
package/src/cookie.ts CHANGED
@@ -19,6 +19,8 @@
19
19
  * mis-spelling fails silently in the direction of a cookie that never expires.
20
20
  */
21
21
 
22
+ import type { JsonValue } from "@jxsuite/schema/types";
23
+
22
24
  /** The cookie attributes an `external-class-def` may declare for the `Cookie` `$prototype`. */
23
25
  export interface CookieOptions {
24
26
  domain?: string | undefined;
@@ -67,11 +69,11 @@ export function readCookie(header: string, name: string): string | null {
67
69
  * - `SameSite=None` requires `Secure` (§5.4.7); without it the cookie is rejected outright.
68
70
  *
69
71
  * @param {string} name
70
- * @param {unknown} value JSON-encoded, then percent-encoded.
72
+ * @param {JsonValue} value JSON-encoded, then percent-encoded.
71
73
  * @param {CookieOptions} options
72
74
  * @returns {string}
73
75
  */
74
- export function serializeCookie(name: string, value: unknown, options: CookieOptions): string {
76
+ export function serializeCookie(name: string, value: JsonValue, options: CookieOptions): string {
75
77
  const hostPrefixed = name.startsWith(HOST_PREFIX);
76
78
  const parts = [`${name}=${encodeURIComponent(JSON.stringify(value))}`];
77
79
 
package/src/css.ts CHANGED
@@ -21,7 +21,7 @@
21
21
  * has to change. This is a narrow door beside the wide one, not a replacement for it.
22
22
  */
23
23
 
24
- import { isRef, isTemplateString } from "@jxsuite/schema/guards";
24
+ import { isNonNullObject, isRef, isString, isTemplateString } from "@jxsuite/schema/guards";
25
25
  import type { JxRef, JxStyle } from "@jxsuite/schema/types";
26
26
 
27
27
  /**
@@ -196,7 +196,10 @@ export function splitSelectorList(selector: string): string[] {
196
196
  }
197
197
  }
198
198
  members.push(selector.slice(start));
199
- const trimmed = members.map((member) => member.trim()).filter((member) => member !== "");
199
+ const trimmed = members.flatMap((member) => {
200
+ const text = member.trim();
201
+ return text === "" ? [] : [text];
202
+ });
200
203
  return trimmed.length > 0 ? trimmed : [selector];
201
204
  }
202
205
 
@@ -257,7 +260,7 @@ function transposeOpenAttribute(selector: string, options: CanvasOverlayTranspos
257
260
  return out + selector.slice(from);
258
261
  }
259
262
  let start = at;
260
- while (start > 0 && !COMPOUND_BREAK.test(selector[start - 1] as string)) {
263
+ while (start > 0 && !COMPOUND_BREAK.test(selector.charAt(start - 1))) {
261
264
  start -= 1;
262
265
  }
263
266
  const type = LEADING_TYPE.exec(selector.slice(start, at))?.[0]?.toLowerCase();
@@ -350,8 +353,16 @@ export const COLOR_SCHEME_STORAGE_KEY = "jx-color-scheme";
350
353
  * @docs framework/concepts/color-schemes
351
354
  */
352
355
  export function pureSchemeOf(query: string): "light" | "dark" | null {
353
- const m = /^\(\s*prefers-color-scheme\s*:\s*(light|dark)\s*\)$/.exec(query.trim());
354
- return (m?.[1] as "light" | "dark") ?? null;
356
+ const scheme = /^\(\s*prefers-color-scheme\s*:\s*(light|dark)\s*\)$/.exec(query.trim())?.[1];
357
+ return scheme === "light" || scheme === "dark" ? scheme : null;
358
+ }
359
+
360
+ /** The two selectors a scheme-conditional rule dual-emits under: see {@link schemeSelectors}. */
361
+ export interface SchemeSelectorPair {
362
+ /** Applies inside the scheme's media query, only while no scheme is forced. */
363
+ auto: string;
364
+ /** Applies unconditionally while the root attribute forces the scheme. */
365
+ forced: string;
355
366
  }
356
367
 
357
368
  /**
@@ -362,13 +373,10 @@ export function pureSchemeOf(query: string): "light" | "dark" | null {
362
373
  *
363
374
  * @param {string} selector
364
375
  * @param {"light" | "dark"} scheme
365
- * @returns {{ auto: string; forced: string }}
376
+ * @returns {SchemeSelectorPair}
366
377
  * @docs framework/concepts/color-schemes
367
378
  */
368
- export function schemeSelectors(
369
- selector: string,
370
- scheme: "light" | "dark",
371
- ): { auto: string; forced: string } {
379
+ export function schemeSelectors(selector: string, scheme: "light" | "dark"): SchemeSelectorPair {
372
380
  if (selector === ":root" || selector === "html") {
373
381
  return {
374
382
  auto: `${selector}:where(:not([${COLOR_SCHEME_ATTR}]))`,
@@ -640,7 +648,9 @@ export function buildStyleRules(style: JxStyle, options: CssBuildOptions = {}):
640
648
  } = options;
641
649
  const rules: CssRule[] = [];
642
650
 
643
- const isBlock = (value: unknown): value is JxStyle =>
651
+ /* `null` is not in the declared value type, but a style object is JSON from a document, and a
652
+ cleared value arrives as `null`. */
653
+ const isBlock = (value: JxStyle[string] | null): value is JxStyle =>
644
654
  value !== null && typeof value === "object" && !Array.isArray(value) && !isRef(value);
645
655
 
646
656
  /**
@@ -658,7 +668,7 @@ export function buildStyleRules(style: JxStyle, options: CssBuildOptions = {}):
658
668
  * the a11y lint, the canvas) assumes a block key holds ONE block; allowing it there would leave
659
669
  * those reading past it in silence, which is the failure this codebase keeps finding.
660
670
  */
661
- const blocksOf = (key: string, value: unknown): JxStyle[] => {
671
+ const blocksOf = (key: string, value: JxStyle[string]): JxStyle[] => {
662
672
  if (isBlock(value)) {
663
673
  return [value];
664
674
  }
@@ -670,7 +680,7 @@ export function buildStyleRules(style: JxStyle, options: CssBuildOptions = {}):
670
680
 
671
681
  const declarationValue = (
672
682
  property: string,
673
- value: unknown,
683
+ value: JxStyle[string] | null,
674
684
  reactive: boolean,
675
685
  target: CssRuleTarget,
676
686
  ): string | null => {
@@ -683,7 +693,7 @@ export function buildStyleRules(style: JxStyle, options: CssBuildOptions = {}):
683
693
  if (isRef(value)) {
684
694
  return reactive ? (resolveValue?.(property, value, target) ?? null) : null;
685
695
  }
686
- if (typeof value === "object") {
696
+ if (isNonNullObject(value)) {
687
697
  return null;
688
698
  }
689
699
  const raw = String(value);
@@ -739,7 +749,7 @@ export function buildStyleRules(style: JxStyle, options: CssBuildOptions = {}):
739
749
  selector: string | null,
740
750
  declarations: readonly (readonly [string, string])[],
741
751
  target: CssRuleTarget,
742
- description?: unknown,
752
+ description?: JxStyle[string],
743
753
  ) => {
744
754
  if (declarations.length === 0) {
745
755
  return;
@@ -753,15 +763,18 @@ export function buildStyleRules(style: JxStyle, options: CssBuildOptions = {}):
753
763
  resolved = transposed;
754
764
  }
755
765
  const text = cssRuleText(conditions, resolved, declarations);
756
- rules.push({
766
+ const rule: CssRule = {
757
767
  text,
758
768
  conditions: [...conditions],
759
769
  selector: resolved,
760
770
  declarations,
761
771
  target,
762
772
  key: hashCss(text),
763
- ...(typeof description === "string" && description !== "" ? { description } : {}),
764
- });
773
+ };
774
+ if (isString(description) && description !== "") {
775
+ rule.description = description;
776
+ }
777
+ rules.push(rule);
765
778
  };
766
779
 
767
780
  /**