@furystack/shades 11.0.19 → 11.0.21

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/README.md CHANGED
@@ -1,43 +1,42 @@
1
1
  # @furystack/shades
2
2
 
3
- Shades is a UI Library for FuryStack with that uses type-safe JSX component, unidirectional data binding and the same DI/IOC, logging and utility libraries as the FuryStack Backend Services.
3
+ Shades is a UI library for FuryStack that uses type-safe JSX components, unidirectional data binding, and the same DI/IoC, logging, and utility libraries as FuryStack backend services.
4
4
 
5
5
  ## Usage
6
6
 
7
7
  You can check the [@furystack/boilerplate](https://github.com/furystack/boilerplate) repository for a working example.
8
8
 
9
- ### A Shade (component)
9
+ ### A Shade (Component)
10
10
 
11
11
  A shade (component) can be constructed from the following properties:
12
12
 
13
- - `ts render:(options: RenderOptions)=>JSX.Element` - A required method that will be executed on each and every render.
14
- - `initialState` - A default state that can be updated during the component lifecycle
15
- - `shadowDomName` can be specified - that will be the custom element's name in the DOM
16
- - `ts constructed: (options: RenderOptions)=>void` is an optional callback that will be executed after component construction. It can return a cleanup method (e.g. free up resources, dispose value observers, etc...)
17
- - `ts onAttach: (options: RenderOptions)=>void` is executed when the component is attached to the DOM
18
- - `ts onDetach: (options: RenderOptions)=>void` is executed when the component is detached from the DOM
13
+ - `render:(options: RenderOptions)=>JSX.Element` A required method that will be executed on each render.
14
+ - `initialState` A default state that can be updated during the component lifecycle.
15
+ - `shadowDomName` Can be specified as the custom element's name in the DOM.
16
+ - `constructed: (options: RenderOptions)=>void` Optional callback executed after component construction. It can return a cleanup method (e.g., free up resources, dispose value observers, etc.).
17
+ - `onAttach: (options: RenderOptions)=>void` Executed when the component is attached to the DOM.
18
+ - `onDetach: (options: RenderOptions)=>void` Executed when the component is detached from the DOM.
19
19
 
20
- ### Render options
20
+ ### Render Options
21
21
 
22
- The lifecycle methods will get the following options from a parameter:
22
+ The lifecycle methods receive the following options as a parameter:
23
23
 
24
- - props - The current readonly **props** object for the element. As props are passed from the parent, it is read only
25
- - getState() - method that will return the current state. State object is also read only and immutable and can be updated with a corresponding method only.
26
- - updateState(newState: TState, skipRender?: boolean) - Updates (patches) the component state. An optional flag can indicate that this state change shouldn't trigger a re-render (e.g. form input fields change, etc...)
27
- - injector - An injector instance. It can be retrieved from the closest parent or can be specified on the _state_ or _props_
28
- - children - The children element(s) of the component
29
- - element - A reference to the current component's custom element (root)
30
- - logger - A specified _logger_ instance with a pre-defined _scope_
24
+ - `props` The current readonly props object for the element. As props are passed from the parent, it is read-only.
25
+ - `getState()` Returns the current state. The state object is also read-only and immutable and can be updated only with a corresponding method.
26
+ - `updateState(newState: TState, skipRender?: boolean)` Updates (patches) the component state. An optional flag can indicate that this state change shouldn't trigger a re-render (e.g., form input fields change, etc.).
27
+ - `injector` An injector instance. It can be retrieved from the closest parent or specified on the state or props.
28
+ - `children` The children element(s) of the component.
29
+ - `element` A reference to the current component's custom element (root).
30
+ - `logger` A specified logger instance with a pre-defined scope.
31
31
 
32
- ### Bundled goodies
32
+ ### Bundled Goodies
33
33
 
34
- The **@furystack/shades** package contains a router component, a router-link component, a location-service and a lazy-load component.
34
+ The **@furystack/shades** package contains a router component, a router-link component, a location service, and a lazy-load component.
35
35
 
36
- ## Core concepts
36
+ ## Core Concepts
37
37
 
38
- - Shade is close to the DOM and the natives. You are encouraged to use native browser methods while you can
39
- - You can use small independent services for state tracking with the _injector_
40
- - ~~Use observable values. Subscribe in the `constructed()` method and dispose them on the callback that it returns.~~
41
- - You can use resources (valueobservers) that will be disposed automatically when your component will be removed from DOM.
42
- - Re-render **can** be skipped on state update. E.g. Why should you break a whole form with a re-render? Why should you update a complete _grid_ if only on item's one field has been changed?
43
- - Nothing is true, everything is permitted 🗡
38
+ - Shade is close to the DOM and the natives. You are encouraged to use native browser methods when possible.
39
+ - You can use small independent services for state tracking with the injector.
40
+ - You can use resources (value observers) that will be disposed automatically when your component is removed from the DOM.
41
+ - Re-rendering can be skipped on state update. For example, why re-render a whole form if only one field has changed?
42
+ - Nothing is true, everything is permitted. 🗡️
@@ -1,12 +1,12 @@
1
- import { TextEncoder, TextDecoder } from 'util';
1
+ import { TextDecoder, TextEncoder } from 'util';
2
2
  global.TextEncoder = TextEncoder;
3
3
  global.TextDecoder = TextDecoder;
4
4
  import { Injector } from '@furystack/inject';
5
- import { RouteLink } from './route-link.js';
6
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
- import { LocationService } from '../services/location-service.js';
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
8
6
  import { initializeShadeRoot } from '../initialize.js';
7
+ import { LocationService } from '../services/location-service.js';
9
8
  import { createComponent } from '../shade-component.js';
9
+ import { RouteLink } from './route-link.js';
10
10
  describe('RouteLink', () => {
11
11
  beforeEach(() => {
12
12
  document.body.innerHTML = '<div id="root"></div>';
@@ -24,7 +24,7 @@ describe('RouteLink', () => {
24
24
  rootElement,
25
25
  jsxElement: (createComponent(RouteLink, { id: "route", href: "/subroute" }, "Link")),
26
26
  });
27
- expect(document.body.innerHTML).toBe('<div id="root"><a is="route-link" id="route" href="/subroute" style="text-decoration: inherit;">Link</a></div>');
27
+ expect(document.body.innerHTML).toMatchInlineSnapshot(`"<div id="root"><a is="route-link" id="route" href="/subroute" style="color: inherit; text-decoration: inherit;">Link</a></div>"`);
28
28
  expect(onRouteChange).not.toBeCalled();
29
29
  document.getElementById('route')?.click();
30
30
  expect(onRouteChange).toBeCalledTimes(1);
@@ -1 +1 @@
1
- {"version":3,"file":"route-link.spec.js","sourceRoot":"","sources":["../../src/components/route-link.spec.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,MAAM,CAAA;AAE/C,MAAM,CAAC,WAAW,GAAG,WAAW,CAAA;AAChC,MAAM,CAAC,WAAW,GAAG,WAAkB,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAEvD,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,uBAAuB,CAAA;IACnD,CAAC,CAAC,CAAA;IACF,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;IAC9B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAA;QAC/B,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAmB,CAAA;QAErE,MAAM,aAAa,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QAE7B,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,qBAAqB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;QAEpF,mBAAmB,CAAC;YAClB,QAAQ;YACR,WAAW;YACX,UAAU,EAAE,CACV,gBAAC,SAAS,IAAC,EAAE,EAAC,OAAO,EAAC,IAAI,EAAC,WAAW,WAE1B,CACb;SACF,CAAC,CAAA;QACF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAClC,gHAAgH,CACjH,CAAA;QACD,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,CAAA;QACtC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAA;QACzC,MAAM,CAAC,aAAa,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"route-link.spec.js","sourceRoot":"","sources":["../../src/components/route-link.spec.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,MAAM,CAAA;AAE/C,MAAM,CAAC,WAAW,GAAG,WAAW,CAAA;AAChC,MAAM,CAAC,WAAW,GAAG,WAAkB,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,uBAAuB,CAAA;IACnD,CAAC,CAAC,CAAA;IACF,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;IAC9B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAA;QAC/B,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAmB,CAAA;QAErE,MAAM,aAAa,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QAE7B,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,qBAAqB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;QAEpF,mBAAmB,CAAC;YAClB,QAAQ;YACR,WAAW;YACX,UAAU,EAAE,CACV,gBAAC,SAAS,IAAC,EAAE,EAAC,OAAO,EAAC,IAAI,EAAC,WAAW,WAE1B,CACb;SACF,CAAC,CAAA;QACF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,qBAAqB,CACnD,kIAAkI,CACnI,CAAA;QACD,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,CAAA;QACtC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAA;QACzC,MAAM,CAAC,aAAa,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@furystack/shades",
3
- "version": "11.0.19",
3
+ "version": "11.0.21",
4
4
  "description": "Google Authentication Provider for FuryStack",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -38,15 +38,15 @@
38
38
  "homepage": "https://github.com/furystack/furystack",
39
39
  "devDependencies": {
40
40
  "@types/jsdom": "^21.1.7",
41
- "@types/node": "^22.15.17",
41
+ "@types/node": "^24.0.1",
42
42
  "jsdom": "^26.1.0",
43
43
  "typescript": "^5.8.3",
44
- "vitest": "^3.1.3"
44
+ "vitest": "^3.2.3"
45
45
  },
46
46
  "dependencies": {
47
- "@furystack/inject": "^12.0.15",
48
- "@furystack/rest": "^8.0.18",
49
- "@furystack/utils": "^8.0.14",
47
+ "@furystack/inject": "^12.0.17",
48
+ "@furystack/rest": "^8.0.20",
49
+ "@furystack/utils": "^8.0.16",
50
50
  "path-to-regexp": "^8.2.0",
51
51
  "semaphore-async-await": "^1.5.1"
52
52
  },
@@ -1,14 +1,14 @@
1
- import { TextEncoder, TextDecoder } from 'util'
1
+ import { TextDecoder, TextEncoder } from 'util'
2
2
 
3
3
  global.TextEncoder = TextEncoder
4
4
  global.TextDecoder = TextDecoder as any
5
5
 
6
6
  import { Injector } from '@furystack/inject'
7
- import { RouteLink } from './route-link.js'
8
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
9
- import { LocationService } from '../services/location-service.js'
7
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
10
8
  import { initializeShadeRoot } from '../initialize.js'
9
+ import { LocationService } from '../services/location-service.js'
11
10
  import { createComponent } from '../shade-component.js'
11
+ import { RouteLink } from './route-link.js'
12
12
 
13
13
  describe('RouteLink', () => {
14
14
  beforeEach(() => {
@@ -35,8 +35,8 @@ describe('RouteLink', () => {
35
35
  </RouteLink>
36
36
  ),
37
37
  })
38
- expect(document.body.innerHTML).toBe(
39
- '<div id="root"><a is="route-link" id="route" href="/subroute" style="text-decoration: inherit;">Link</a></div>',
38
+ expect(document.body.innerHTML).toMatchInlineSnapshot(
39
+ `"<div id="root"><a is="route-link" id="route" href="/subroute" style="color: inherit; text-decoration: inherit;">Link</a></div>"`,
40
40
  )
41
41
  expect(onRouteChange).not.toBeCalled()
42
42
  document.getElementById('route')?.click()