@furystack/shades-nipple 7.0.35 → 8.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # Changelog
2
2
 
3
+ ## [8.0.0] - 2026-02-09
4
+
5
+ ### ⬆️ Dependencies
6
+
7
+ - Updated peer dependency `@furystack/shades` to latest minor version
8
+ - Updated `@furystack/shades` dependency with microtask-based batched rendering
9
+ - Peer dependency on `@furystack/shades` bumped to new major version
10
+ - Updated `@furystack/shades` dependency
11
+
12
+ ### 💥 Breaking Changes
13
+
14
+ ### Requires `@furystack/shades` v3
15
+
16
+ This package now depends on the new major version of `@furystack/shades` which removed the `constructed` callback.
17
+
18
+ ### Migrated from `element` to `useRef` for Zone Management
19
+
20
+ The `NippleComponent` no longer uses the `element` render option as the nipplejs zone. Instead, it uses `useRef` to reference a dedicated container `<div>`, which is passed to `nipplejs.create()` as the zone.
21
+
22
+ **Impact:** The nipplejs manager is now attached to a child `<div>` inside the component rather than the host custom element itself. This should be transparent for most consumers.
23
+
24
+ ### ♻️ Refactoring
25
+
26
+ - Migrated `NippleComponent` from async `constructed` callback to `useDisposable()` in `render` for nipplejs manager initialization and cleanup
27
+ - Replaced `element` parameter with `useRef('zone')` and a container `<div>` for nipplejs initialization
28
+ - Nipple manager creation now deferred via `queueMicrotask` to ensure the ref is available after the first render
29
+
30
+ ### 🧪 Tests
31
+
32
+ - Refactored `Nipple` component tests to use `usingAsync` for proper `Injector` disposal
33
+
34
+ ## [7.0.36] - 2026-02-01
35
+
36
+ ### ⬆️ Dependencies
37
+
38
+ - Updated peer dependency `@furystack/shades` to include new CSS styling features
39
+
3
40
  ## [7.0.35] - 2026-01-26
4
41
 
5
42
  ### 🔧 Chores
package/esm/nipple.d.ts CHANGED
@@ -9,5 +9,7 @@ export interface NippleComponentProps {
9
9
  }
10
10
  export declare const NippleComponent: (props: NippleComponentProps & Omit<Partial<HTMLElement>, "style"> & {
11
11
  style?: Partial<CSSStyleDeclaration>;
12
+ } & {
13
+ ref?: import("@furystack/shades").RefObject<Element>;
12
14
  }, children?: import("@furystack/shades").ChildrenList) => JSX.Element;
13
15
  //# sourceMappingURL=nipple.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"nipple.d.ts","sourceRoot":"","sources":["../src/nipple.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAGrF,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,sBAAsB,CAAA;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAA;IACpC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC5D,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC1D,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC1D,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;CAC5D;AAED,eAAO,MAAM,eAAe;;sEA2B1B,CAAA"}
1
+ {"version":3,"file":"nipple.d.ts","sourceRoot":"","sources":["../src/nipple.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAGrF,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,sBAAsB,CAAA;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAA;IACpC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC5D,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC1D,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC1D,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;CAC5D;AAED,eAAO,MAAM,eAAe;;;;sEAkC1B,CAAA"}
package/esm/nipple.js CHANGED
@@ -2,30 +2,36 @@ import { Shade, createComponent } from '@furystack/shades';
2
2
  import nipplejs from 'nipplejs';
3
3
  export const NippleComponent = Shade({
4
4
  shadowDomName: 'shade-nipple',
5
- constructed: async ({ element, props }) => {
6
- const manager = nipplejs.create({
7
- zone: element,
8
- ...props.managerOptions,
5
+ render: ({ children, props, useDisposable, useRef }) => {
6
+ const zoneRef = useRef('zone');
7
+ useDisposable('nipple-init', () => {
8
+ let manager;
9
+ queueMicrotask(() => {
10
+ if (!zoneRef.current)
11
+ return;
12
+ manager = nipplejs.create({
13
+ zone: zoneRef.current,
14
+ ...props.managerOptions,
15
+ });
16
+ if (props.onStart) {
17
+ manager.on('start', props.onStart);
18
+ }
19
+ if (props.onEnd) {
20
+ manager.on('end', props.onEnd);
21
+ }
22
+ if (props.onDir) {
23
+ manager.on('dir', props.onDir);
24
+ }
25
+ if (props.onMove) {
26
+ manager.on('move', props.onMove);
27
+ }
28
+ });
29
+ return { [Symbol.dispose]: () => manager?.destroy() };
9
30
  });
10
- if (props.onStart) {
11
- manager.on('start', props.onStart);
12
- }
13
- if (props.onEnd) {
14
- manager.on('end', props.onEnd);
15
- }
16
- if (props.onDir) {
17
- manager.on('dir', props.onDir);
18
- }
19
- if (props.onMove) {
20
- manager.on('move', props.onMove);
21
- }
22
- return () => manager.destroy();
23
- },
24
- render: ({ children }) => {
25
31
  if (children) {
26
- return createComponent(createComponent, null, children);
32
+ return createComponent("div", { ref: zoneRef }, children);
27
33
  }
28
- return createComponent("div", null);
34
+ return createComponent("div", { ref: zoneRef });
29
35
  },
30
36
  });
31
37
  //# sourceMappingURL=nipple.js.map
package/esm/nipple.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"nipple.js","sourceRoot":"","sources":["../src/nipple.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAE1D,OAAO,QAAQ,MAAM,UAAU,CAAA;AAW/B,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAuB;IACzD,aAAa,EAAE,cAAc;IAC7B,WAAW,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC9B,IAAI,EAAE,OAAO;YACb,GAAG,KAAK,CAAC,cAAc;SACxB,CAAC,CAAA;QACF,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;QACpC,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;QAChC,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;QAChC,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;QAClC,CAAC;QACD,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAA;IAChC,CAAC;IACD,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;QACvB,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,uCAAG,QAAQ,CAAI,CAAA;QACxB,CAAC;QACD,OAAO,4BAAO,CAAA;IAChB,CAAC;CACF,CAAC,CAAA"}
1
+ {"version":3,"file":"nipple.js","sourceRoot":"","sources":["../src/nipple.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAE1D,OAAO,QAAQ,MAAM,UAAU,CAAA;AAW/B,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAuB;IACzD,aAAa,EAAE,cAAc;IAC7B,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE;QACrD,MAAM,OAAO,GAAG,MAAM,CAAiB,MAAM,CAAC,CAAA;QAE9C,aAAa,CAAC,aAAa,EAAE,GAAG,EAAE;YAChC,IAAI,OAAuD,CAAA;YAC3D,cAAc,CAAC,GAAG,EAAE;gBAClB,IAAI,CAAC,OAAO,CAAC,OAAO;oBAAE,OAAM;gBAC5B,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC;oBACxB,IAAI,EAAE,OAAO,CAAC,OAAO;oBACrB,GAAG,KAAK,CAAC,cAAc;iBACxB,CAAC,CAAA;gBACF,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;oBAClB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;gBACpC,CAAC;gBACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oBAChB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;gBAChC,CAAC;gBACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oBAChB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;gBAChC,CAAC;gBACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;oBACjB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;gBAClC,CAAC;YACH,CAAC,CAAC,CAAA;YACF,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAA;QACvD,CAAC,CAAC,CAAA;QAEF,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,yBAAK,GAAG,EAAE,OAAO,IAAG,QAAQ,CAAO,CAAA;QAC5C,CAAC;QACD,OAAO,yBAAK,GAAG,EAAE,OAAO,GAAI,CAAA;IAC9B,CAAC;CACF,CAAC,CAAA"}
@@ -1,7 +1,8 @@
1
1
  import { Injector } from '@furystack/inject';
2
2
  import { createComponent, initializeShadeRoot } from '@furystack/shades';
3
+ import { usingAsync } from '@furystack/utils';
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
5
  import { NippleComponent } from './nipple.js';
4
- import { describe, it, expect, afterEach, beforeEach, vi } from 'vitest';
5
6
  describe('Nipple', () => {
6
7
  beforeEach(() => {
7
8
  document.body.innerHTML = '<div id="root"></div>';
@@ -9,35 +10,37 @@ describe('Nipple', () => {
9
10
  afterEach(() => {
10
11
  document.body.innerHTML = '';
11
12
  });
12
- it('Should render with the default settings', () => {
13
- const injector = new Injector();
14
- const rootElement = document.getElementById('root');
15
- initializeShadeRoot({
16
- injector,
17
- rootElement,
18
- jsxElement: createComponent(NippleComponent, { managerOptions: {} }),
13
+ it('Should render with the default settings', async () => {
14
+ await usingAsync(new Injector(), async (injector) => {
15
+ const rootElement = document.getElementById('root');
16
+ initializeShadeRoot({
17
+ injector,
18
+ rootElement,
19
+ jsxElement: createComponent(NippleComponent, { managerOptions: {} }),
20
+ });
21
+ expect(document.body.innerHTML).toBe('<div id="root"><shade-nipple></shade-nipple></div>');
19
22
  });
20
- expect(document.body.innerHTML).toBe('<div id="root"><shade-nipple></shade-nipple></div>');
21
23
  });
22
24
  it('Should attach event properties', async () => {
23
- const injector = new Injector();
24
- const rootElement = document.getElementById('root');
25
- const onStart = vi.fn();
26
- const onDir = vi.fn();
27
- const onMove = vi.fn();
28
- const onEnd = vi.fn();
29
- initializeShadeRoot({
30
- injector,
31
- rootElement,
32
- jsxElement: createComponent(NippleComponent, { onStart: onStart, onDir: onDir, onMove: onMove, onEnd: onEnd, managerOptions: {} }),
25
+ await usingAsync(new Injector(), async (injector) => {
26
+ const rootElement = document.getElementById('root');
27
+ const onStart = vi.fn();
28
+ const onDir = vi.fn();
29
+ const onMove = vi.fn();
30
+ const onEnd = vi.fn();
31
+ initializeShadeRoot({
32
+ injector,
33
+ rootElement,
34
+ jsxElement: (createComponent(NippleComponent, { onStart: onStart, onDir: onDir, onMove: onMove, onEnd: onEnd, managerOptions: {} })),
35
+ });
36
+ expect(document.body.innerHTML).toBe('<div id="root"><shade-nipple></shade-nipple></div>');
37
+ const nipple = document.querySelector('shade-nipple');
38
+ expect(nipple.props.onDir).toBe(onDir);
39
+ expect(nipple.props.onEnd).toBe(onEnd);
40
+ expect(nipple.props.onMove).toBe(onMove);
41
+ expect(nipple.props.onStart).toBe(onStart);
42
+ // TODO: Check for pointer events
33
43
  });
34
- expect(document.body.innerHTML).toBe('<div id="root"><shade-nipple></shade-nipple></div>');
35
- const nipple = document.querySelector('shade-nipple');
36
- expect(nipple.props.onDir).toBe(onDir);
37
- expect(nipple.props.onEnd).toBe(onEnd);
38
- expect(nipple.props.onMove).toBe(onMove);
39
- expect(nipple.props.onStart).toBe(onStart);
40
- // TODO: Check for pointer events
41
44
  });
42
45
  });
43
46
  //# sourceMappingURL=nipple.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nipple.spec.js","sourceRoot":"","sources":["../src/nipple.spec.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAExE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAExE,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,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;IACF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAA;QAC/B,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAmB,CAAA;QAErE,mBAAmB,CAAC;YAClB,QAAQ;YACR,WAAW;YACX,UAAU,EAAE,gBAAC,eAAe,IAAC,cAAc,EAAE,EAAE,GAAI;SACpD,CAAC,CAAA;QACF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;IAC5F,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAA;QAC/B,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAmB,CAAA;QAErE,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QACvB,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QACrB,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QACtB,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QAErB,mBAAmB,CAAC;YAClB,QAAQ;YACR,WAAW;YACX,UAAU,EAAE,gBAAC,eAAe,IAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,GAAI;SAClH,CAAC,CAAA;QACF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;QAC1F,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,cAAc,CAAsC,CAAA;QAE1F,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACxC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAE1C,iCAAiC;IACnC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"nipple.spec.js","sourceRoot":"","sources":["../src/nipple.spec.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAExE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,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;IACF,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClD,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAmB,CAAA;YAErE,mBAAmB,CAAC;gBAClB,QAAQ;gBACR,WAAW;gBACX,UAAU,EAAE,gBAAC,eAAe,IAAC,cAAc,EAAE,EAAE,GAAI;aACpD,CAAC,CAAA;YACF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;QAC5F,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClD,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAmB,CAAA;YAErE,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;YACvB,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;YACrB,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;YACtB,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;YAErB,mBAAmB,CAAC;gBAClB,QAAQ;gBACR,WAAW;gBACX,UAAU,EAAE,CACV,gBAAC,eAAe,IAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,GAAI,CACtG;aACF,CAAC,CAAA;YACF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;YAC1F,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,cAAc,CAAsC,CAAA;YAE1F,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACtC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACtC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACxC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAE1C,iCAAiC;QACnC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@furystack/shades-nipple",
3
- "version": "7.0.35",
3
+ "version": "8.0.0",
4
4
  "description": "A Nipple component wrapper for FuryStack Shades",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -38,12 +38,12 @@
38
38
  },
39
39
  "homepage": "https://github.com/furystack/furystack",
40
40
  "devDependencies": {
41
- "@furystack/inject": "^12.0.28",
41
+ "@furystack/inject": "^12.0.29",
42
42
  "typescript": "^5.9.3",
43
43
  "vitest": "^4.0.17"
44
44
  },
45
45
  "dependencies": {
46
- "@furystack/shades": "^11.0.35",
46
+ "@furystack/shades": "^12.0.0",
47
47
  "nipplejs": "^0.10.2"
48
48
  },
49
49
  "engines": {
@@ -1,8 +1,9 @@
1
1
  import { Injector } from '@furystack/inject'
2
2
  import { createComponent, initializeShadeRoot } from '@furystack/shades'
3
+ import { usingAsync } from '@furystack/utils'
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
3
5
  import type { NippleComponentProps } from './nipple.js'
4
6
  import { NippleComponent } from './nipple.js'
5
- import { describe, it, expect, afterEach, beforeEach, vi } from 'vitest'
6
7
 
7
8
  describe('Nipple', () => {
8
9
  beforeEach(() => {
@@ -11,40 +12,44 @@ describe('Nipple', () => {
11
12
  afterEach(() => {
12
13
  document.body.innerHTML = ''
13
14
  })
14
- it('Should render with the default settings', () => {
15
- const injector = new Injector()
16
- const rootElement = document.getElementById('root') as HTMLDivElement
15
+ it('Should render with the default settings', async () => {
16
+ await usingAsync(new Injector(), async (injector) => {
17
+ const rootElement = document.getElementById('root') as HTMLDivElement
17
18
 
18
- initializeShadeRoot({
19
- injector,
20
- rootElement,
21
- jsxElement: <NippleComponent managerOptions={{}} />,
19
+ initializeShadeRoot({
20
+ injector,
21
+ rootElement,
22
+ jsxElement: <NippleComponent managerOptions={{}} />,
23
+ })
24
+ expect(document.body.innerHTML).toBe('<div id="root"><shade-nipple></shade-nipple></div>')
22
25
  })
23
- expect(document.body.innerHTML).toBe('<div id="root"><shade-nipple></shade-nipple></div>')
24
26
  })
25
27
 
26
28
  it('Should attach event properties', async () => {
27
- const injector = new Injector()
28
- const rootElement = document.getElementById('root') as HTMLDivElement
29
+ await usingAsync(new Injector(), async (injector) => {
30
+ const rootElement = document.getElementById('root') as HTMLDivElement
29
31
 
30
- const onStart = vi.fn()
31
- const onDir = vi.fn()
32
- const onMove = vi.fn()
33
- const onEnd = vi.fn()
32
+ const onStart = vi.fn()
33
+ const onDir = vi.fn()
34
+ const onMove = vi.fn()
35
+ const onEnd = vi.fn()
34
36
 
35
- initializeShadeRoot({
36
- injector,
37
- rootElement,
38
- jsxElement: <NippleComponent onStart={onStart} onDir={onDir} onMove={onMove} onEnd={onEnd} managerOptions={{}} />,
39
- })
40
- expect(document.body.innerHTML).toBe('<div id="root"><shade-nipple></shade-nipple></div>')
41
- const nipple = document.querySelector('shade-nipple') as JSX.Element<NippleComponentProps>
37
+ initializeShadeRoot({
38
+ injector,
39
+ rootElement,
40
+ jsxElement: (
41
+ <NippleComponent onStart={onStart} onDir={onDir} onMove={onMove} onEnd={onEnd} managerOptions={{}} />
42
+ ),
43
+ })
44
+ expect(document.body.innerHTML).toBe('<div id="root"><shade-nipple></shade-nipple></div>')
45
+ const nipple = document.querySelector('shade-nipple') as JSX.Element<NippleComponentProps>
42
46
 
43
- expect(nipple.props.onDir).toBe(onDir)
44
- expect(nipple.props.onEnd).toBe(onEnd)
45
- expect(nipple.props.onMove).toBe(onMove)
46
- expect(nipple.props.onStart).toBe(onStart)
47
+ expect(nipple.props.onDir).toBe(onDir)
48
+ expect(nipple.props.onEnd).toBe(onEnd)
49
+ expect(nipple.props.onMove).toBe(onMove)
50
+ expect(nipple.props.onStart).toBe(onStart)
47
51
 
48
- // TODO: Check for pointer events
52
+ // TODO: Check for pointer events
53
+ })
49
54
  })
50
55
  })
package/src/nipple.tsx CHANGED
@@ -13,29 +13,36 @@ export interface NippleComponentProps {
13
13
 
14
14
  export const NippleComponent = Shade<NippleComponentProps>({
15
15
  shadowDomName: 'shade-nipple',
16
- constructed: async ({ element, props }) => {
17
- const manager = nipplejs.create({
18
- zone: element,
19
- ...props.managerOptions,
16
+ render: ({ children, props, useDisposable, useRef }) => {
17
+ const zoneRef = useRef<HTMLDivElement>('zone')
18
+
19
+ useDisposable('nipple-init', () => {
20
+ let manager: ReturnType<typeof nipplejs.create> | undefined
21
+ queueMicrotask(() => {
22
+ if (!zoneRef.current) return
23
+ manager = nipplejs.create({
24
+ zone: zoneRef.current,
25
+ ...props.managerOptions,
26
+ })
27
+ if (props.onStart) {
28
+ manager.on('start', props.onStart)
29
+ }
30
+ if (props.onEnd) {
31
+ manager.on('end', props.onEnd)
32
+ }
33
+ if (props.onDir) {
34
+ manager.on('dir', props.onDir)
35
+ }
36
+ if (props.onMove) {
37
+ manager.on('move', props.onMove)
38
+ }
39
+ })
40
+ return { [Symbol.dispose]: () => manager?.destroy() }
20
41
  })
21
- if (props.onStart) {
22
- manager.on('start', props.onStart)
23
- }
24
- if (props.onEnd) {
25
- manager.on('end', props.onEnd)
26
- }
27
- if (props.onDir) {
28
- manager.on('dir', props.onDir)
29
- }
30
- if (props.onMove) {
31
- manager.on('move', props.onMove)
32
- }
33
- return () => manager.destroy()
34
- },
35
- render: ({ children }) => {
42
+
36
43
  if (children) {
37
- return <>{children}</>
44
+ return <div ref={zoneRef}>{children}</div>
38
45
  }
39
- return <div />
46
+ return <div ref={zoneRef} />
40
47
  },
41
48
  })