@furystack/shades 15.0.0 → 15.0.1

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 (60) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/esm/compile-route.d.ts +5 -0
  3. package/esm/compile-route.d.ts.map +1 -1
  4. package/esm/compile-route.js +5 -0
  5. package/esm/compile-route.js.map +1 -1
  6. package/esm/components/nested-router.js.map +1 -1
  7. package/esm/css-generator.d.ts +9 -26
  8. package/esm/css-generator.d.ts.map +1 -1
  9. package/esm/css-generator.js +9 -26
  10. package/esm/css-generator.js.map +1 -1
  11. package/esm/css-generator.spec.js.map +1 -1
  12. package/esm/models/css-object.d.ts +3 -5
  13. package/esm/models/css-object.d.ts.map +1 -1
  14. package/esm/models/render-options.d.ts +16 -20
  15. package/esm/models/render-options.d.ts.map +1 -1
  16. package/esm/models/shade-component.d.ts +6 -4
  17. package/esm/models/shade-component.d.ts.map +1 -1
  18. package/esm/models/shade-component.js +3 -3
  19. package/esm/models/shade-component.js.map +1 -1
  20. package/esm/services/route-meta-utils.js.map +1 -1
  21. package/esm/services/screen-service.spec.js.map +1 -1
  22. package/esm/shade-component.d.ts +14 -17
  23. package/esm/shade-component.d.ts.map +1 -1
  24. package/esm/shade-component.js +14 -17
  25. package/esm/shade-component.js.map +1 -1
  26. package/esm/shade.d.ts +17 -14
  27. package/esm/shade.d.ts.map +1 -1
  28. package/esm/shade.js +12 -25
  29. package/esm/shade.js.map +1 -1
  30. package/esm/style-manager.d.ts +8 -22
  31. package/esm/style-manager.d.ts.map +1 -1
  32. package/esm/style-manager.js +8 -22
  33. package/esm/style-manager.js.map +1 -1
  34. package/esm/styled-shade.d.ts +4 -7
  35. package/esm/styled-shade.d.ts.map +1 -1
  36. package/esm/styled-shade.js +4 -4
  37. package/esm/styled-shade.js.map +1 -1
  38. package/esm/view-transition.d.ts +10 -22
  39. package/esm/view-transition.d.ts.map +1 -1
  40. package/esm/view-transition.js +10 -22
  41. package/esm/view-transition.js.map +1 -1
  42. package/esm/vnode.js.map +1 -1
  43. package/esm/vnode.spec.js.map +1 -1
  44. package/package.json +9 -9
  45. package/src/compile-route.ts +5 -0
  46. package/src/components/nested-router.tsx +2 -2
  47. package/src/css-generator.spec.ts +1 -1
  48. package/src/css-generator.ts +9 -26
  49. package/src/models/css-object.ts +3 -5
  50. package/src/models/render-options.ts +17 -20
  51. package/src/models/shade-component.ts +6 -4
  52. package/src/services/route-meta-utils.ts +1 -1
  53. package/src/services/screen-service.spec.ts +2 -2
  54. package/src/shade-component.ts +14 -17
  55. package/src/shade.ts +20 -33
  56. package/src/style-manager.ts +9 -22
  57. package/src/styled-shade.ts +5 -8
  58. package/src/view-transition.ts +10 -22
  59. package/src/vnode.spec.ts +3 -3
  60. package/src/vnode.ts +2 -2
@@ -1,19 +1,16 @@
1
1
  import { generateCSS } from './css-generator.js'
2
2
  import type { CSSObject } from './models/css-object.js'
3
+ import type { Shade } from './shade.js'
3
4
 
4
5
  /**
5
- * Singleton that manages component CSS injection.
6
- * Creates and maintains a shared `<style>` element in the document head,
7
- * and tracks registered component styles to avoid duplicates.
6
+ * Owns a shared `<style data-shades-styles>` element in `document.head`
7
+ * and dedupes component-style registration. Internal — consumers use
8
+ * the {@link StyleManager} singleton.
8
9
  */
9
10
  class StyleManagerClass {
10
11
  private styleElement: HTMLStyleElement | null = null
11
12
  private registeredComponents = new Set<string>()
12
13
 
13
- /**
14
- * Gets or creates the shared style element
15
- * @returns The style element for CSS injection
16
- */
17
14
  private getStyleElement(): HTMLStyleElement {
18
15
  if (!this.styleElement) {
19
16
  this.styleElement = document.createElement('style')
@@ -66,26 +63,16 @@ class StyleManagerClass {
66
63
  return false
67
64
  }
68
65
 
69
- /**
70
- * Checks if a component's styles have already been registered
71
- * @param customElementName - The component identifier to check
72
- * @returns True if styles are already registered
73
- */
74
66
  public isRegistered(customElementName: string): boolean {
75
67
  return this.registeredComponents.has(customElementName)
76
68
  }
77
69
 
78
- /**
79
- * Gets all registered component names (for debugging/testing)
80
- * @returns Set of registered component names
81
- */
70
+ /** Snapshot of registered component names. Intended for diagnostics + tests. */
82
71
  public getRegisteredComponents(): ReadonlySet<string> {
83
72
  return this.registeredComponents
84
73
  }
85
74
 
86
- /**
87
- * Clears all registered styles (useful for testing)
88
- */
75
+ /** Removes the shared style element and clears the registration set. Test-only. */
89
76
  public clear(): void {
90
77
  this.registeredComponents.clear()
91
78
  if (this.styleElement) {
@@ -97,8 +84,8 @@ class StyleManagerClass {
97
84
  }
98
85
 
99
86
  /**
100
- * Singleton instance for managing component CSS styles.
101
- * Use this to register component-level styles that support
102
- * pseudo-selectors and nested selectors.
87
+ * Process-wide CSS injection registry for Shade components. The {@link Shade}
88
+ * factory calls `registerComponentStyles` automatically; direct use is rare
89
+ * (e.g. injecting a third-party stylesheet keyed off a component name).
103
90
  */
104
91
  export const StyleManager = new StyleManagerClass()
@@ -1,17 +1,14 @@
1
1
  import type { ChildrenList } from './models/children-list.js'
2
2
 
3
- /**
4
- * Props constraint for styled components - must have an optional style property
5
- */
6
3
  type StyledProps = {
7
4
  style?: Partial<CSSStyleDeclaration>
8
5
  }
9
6
 
10
7
  /**
11
- * Creates a shortcut for a specific custom Shade element with additional styles
12
- * @param element The element instance
13
- * @param styles The additional styles to add
14
- * @returns The updated element
8
+ * Wraps a Shade factory with a baked-in `style` overlay. Baked-in `styles`
9
+ * win over caller-supplied `style` props (the wrapper merges last). Use to
10
+ * specialise an existing Shade (e.g. theme variants) without registering
11
+ * a new custom element.
15
12
  */
16
13
  export const styledShade = <TProps extends StyledProps>(
17
14
  element: (props: TProps, children?: ChildrenList) => JSX.Element,
@@ -25,7 +22,7 @@ export const styledShade = <TProps extends StyledProps>(
25
22
  ...props.style,
26
23
  ...styles,
27
24
  },
28
- } as TProps,
25
+ },
29
26
  childrenList,
30
27
  )
31
28
  }
@@ -8,16 +8,13 @@ export type ViewTransitionConfig = {
8
8
  }
9
9
 
10
10
  /**
11
- * Wraps a DOM update in `document.startViewTransition()` when the View Transition API
12
- * is available and `config` is truthy. Falls back to calling `update()` directly otherwise.
11
+ * Runs `update` inside `document.startViewTransition()` when the API is
12
+ * available and `config` is truthy; otherwise calls `update` synchronously.
13
13
  *
14
- * Returns the `updateCallbackDone` promise when a transition is started, allowing callers
15
- * that need to wait for the DOM update (e.g. to run lifecycle hooks) to `await` the result.
16
- * Returns `undefined` when no transition is used (the update runs synchronously).
17
- *
18
- * @param config - The view transition configuration (boolean or object with types)
19
- * @param update - The synchronous DOM update callback
20
- * @returns A promise that resolves after the update callback completes inside the transition, or `undefined`
14
+ * The returned promise (when a transition starts) resolves once the update
15
+ * callback completes inside the transition — callers that need to chain
16
+ * lifecycle work after the DOM swap can `await` it. Returns `undefined`
17
+ * when no transition is used.
21
18
  */
22
19
  export const maybeViewTransition = (
23
20
  config: boolean | ViewTransitionConfig | undefined,
@@ -33,19 +30,10 @@ export const maybeViewTransition = (
33
30
  }
34
31
 
35
32
  /**
36
- * Keeps a "displayed" copy of `value` that is updated through a view transition
37
- * whenever the value changes and `shouldTransition` returns true.
38
- *
39
- * When the transition is skipped (config is falsy or `shouldTransition` returns false),
40
- * the displayed value is updated synchronously without an animation.
41
- *
42
- * @param useState - The component's `useState` hook
43
- * @param key - Unique state key for caching the displayed value
44
- * @param value - The latest source value (e.g. from `useObservable` or derived from props)
45
- * @param config - View transition configuration forwarded to `maybeViewTransition`
46
- * @param shouldTransition - Predicate that decides whether a value change warrants a transition.
47
- * Defaults to `() => true` (always transition).
48
- * @returns The currently displayed value
33
+ * Decouples a component's "displayed" value from its source. When `value`
34
+ * changes and `shouldTransition(prev, next)` returns true, the swap is
35
+ * routed through {@link maybeViewTransition}; otherwise the displayed
36
+ * value updates synchronously. `shouldTransition` defaults to always-true.
49
37
  */
50
38
  export const transitionedValue = <T>(
51
39
  useState: <S>(key: string, initialValue: S) => [S, (v: S) => void],
package/src/vnode.spec.ts CHANGED
@@ -545,7 +545,7 @@ describe('vnode', () => {
545
545
  ;(fakeShadeEl as unknown as Record<string, unknown>).props = { count: 1 }
546
546
  ;(fakeShadeEl as unknown as Record<string, unknown>).shadeChildren = undefined
547
547
 
548
- const factory = vi.fn(() => fakeShadeEl as unknown as JSX.Element)
548
+ const factory = vi.fn(() => fakeShadeEl)
549
549
 
550
550
  const old: VChild[] = [{ _brand: 'vnode', type: factory, props: { count: 1 }, children: [], _el: fakeShadeEl }]
551
551
  parent.appendChild(fakeShadeEl)
@@ -566,7 +566,7 @@ describe('vnode', () => {
566
566
  ;(fakeShadeEl as unknown as Record<string, unknown>).props = { elevation: 2 }
567
567
  ;(fakeShadeEl as unknown as Record<string, unknown>).shadeChildren = undefined
568
568
 
569
- const factory = vi.fn(() => fakeShadeEl as unknown as JSX.Element)
569
+ const factory = vi.fn(() => fakeShadeEl)
570
570
 
571
571
  const old: VChild[] = [
572
572
  { _brand: 'vnode', type: factory, props: { elevation: 2 }, children: [], _el: fakeShadeEl },
@@ -591,7 +591,7 @@ describe('vnode', () => {
591
591
  ;(fakeShadeEl as unknown as Record<string, unknown>).props = props
592
592
  ;(fakeShadeEl as unknown as Record<string, unknown>).shadeChildren = undefined
593
593
 
594
- const factory = vi.fn(() => fakeShadeEl as unknown as JSX.Element)
594
+ const factory = vi.fn(() => fakeShadeEl)
595
595
 
596
596
  const old: VChild[] = [{ _brand: 'vnode', type: factory, props: { count: 1 }, children: [], _el: fakeShadeEl }]
597
597
  parent.appendChild(fakeShadeEl)
package/src/vnode.ts CHANGED
@@ -197,9 +197,9 @@ export const toVChildArray = (renderResult: unknown): VChild[] => {
197
197
  // Real DOM element (from async code that ran outside renderMode)
198
198
  if (renderResult instanceof DocumentFragment) {
199
199
  return Array.from(renderResult.childNodes).map((node) => ({
200
- _brand: VNODE_BRAND as typeof VNODE_BRAND,
200
+ _brand: VNODE_BRAND,
201
201
  type: EXISTING_NODE,
202
- props: {} as Record<string, unknown>,
202
+ props: {},
203
203
  children: [] as VChild[],
204
204
  _el: node,
205
205
  }))