vultus-core 0.3.0 → 0.4.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/README.md CHANGED
@@ -22,8 +22,10 @@ npm install vultus-core
22
22
  `parseApiError`, `routeApiError`, `ActionErrorContext` / `useActionErrorCtx`,
23
23
  `useAction`, `useActionList`, the fields (`useBoolField`, `useFieldCore` and
24
24
  their types), `InternalLinkContext` / `useInternalLink` /
25
- `InternalLinkComponent`, and `MessageSinkContext` / `useMessageSink` /
26
- `MessageSink`.
25
+ `InternalLinkComponent`, `MessageSinkContext` / `useMessageSink` /
26
+ `MessageSink`, and `VultusComponentsContext` / `useVultusComponents` /
27
+ `SpinnerScope` / `useSpinnerKey` / `VultusComponents` / `SpinnerProps` /
28
+ `SpinnerComponent`.
27
29
  - `./link` — `InternalLinkContext`, `useInternalLink`, and the
28
30
  `InternalLinkComponent` type on their own, for consumers that only need the
29
31
  link-injection seam.
@@ -71,6 +73,21 @@ boolean field (inside: `initialValue`, default the first enabled choice); `confi
71
73
  depend on the requested choice. vultus-antd's `OneOfSelect` and `OneOfSegmented` take the
72
74
  same field.
73
75
 
76
+ ## Components
77
+
78
+ `VultusComponentsContext` (default `{}`) / `useVultusComponents()` is how an app lends its own
79
+ UI to vultus/optio in place of their native indicators — today just `Spinner` (`SpinnerProps`:
80
+ `spinnerKey`, `size?`, `label?`; `VultusComponents.Spinner?: SpinnerComponent`). vultus-antd's
81
+ `VultusProvider` merges a `components` prop into the outer context value; without one, the
82
+ outer value (or this default) applies, as `linkComponent` does today.
83
+
84
+ Every call site that may render a lent `Spinner` asks for its key through `useSpinnerKey(localKey)`
85
+ rather than hardcoding it, so an app can scope a whole subtree's keys to one instance:
86
+ `<SpinnerScope name="optio:process:p1">` makes every `useSpinnerKey` call inside it return
87
+ `'optio:process:p1/' + localKey`; scopes nest by joining names with `/`, outermost first.
88
+ Library-local keys are namespaced (`vultus:...`, `optio:...`) so they never collide with an
89
+ app's own keys.
90
+
74
91
  ## Distribution
75
92
 
76
93
  This package ships compiled ESM (`dist/`) with TypeScript declarations to
@@ -0,0 +1,30 @@
1
+ import { type ComponentType, type ReactNode } from 'react';
2
+ /** A spinner an app lends to vultus/optio, rendered in place of their native loading indicators. */
3
+ export interface SpinnerProps {
4
+ /** The spinner's identity: stable across re-renders and remounts, unique on the page (after scoping). */
5
+ spinnerKey: string;
6
+ /** antd's names (the height of antd's Spin indicator) or a height in px. */
7
+ size?: 'small' | 'default' | 'large' | number;
8
+ /** Accessible label; the spinner's own default when omitted. */
9
+ label?: string;
10
+ }
11
+ export type SpinnerComponent = ComponentType<SpinnerProps>;
12
+ /** Components an app lends to the libraries. */
13
+ export interface VultusComponents {
14
+ Spinner?: SpinnerComponent;
15
+ }
16
+ /**
17
+ * The components an app lends to vultus/optio in place of their own UI. Default is `{}`
18
+ * (none lent) so vultus-core stays framework-neutral; vultus-antd's `VultusProvider` merges
19
+ * in whatever an app passes as `components`.
20
+ */
21
+ export declare const VultusComponentsContext: import("react").Context<VultusComponents>;
22
+ export declare function useVultusComponents(): VultusComponents;
23
+ /** Prefixes every spinner key below with `name` (scopes nest: outer/inner). */
24
+ export declare function SpinnerScope({ name, children }: {
25
+ name: string;
26
+ children?: ReactNode;
27
+ }): import("react").JSX.Element;
28
+ /** The scoped key for a library-local key: 'outer/inner/local', or 'local' outside any scope. */
29
+ export declare function useSpinnerKey(localKey: string): string;
30
+ //# sourceMappingURL=Components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Components.d.ts","sourceRoot":"","sources":["../src/Components.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE/F,oGAAoG;AACpG,MAAM,WAAW,YAAY;IAC3B,yGAAyG;IACzG,UAAU,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IAC9C,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;AAE3D,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,2CAAsC,CAAC;AAE3E,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD;AAKD,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,+BAOtF;AAED,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGtD"}
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext, useMemo } from 'react';
3
+ /**
4
+ * The components an app lends to vultus/optio in place of their own UI. Default is `{}`
5
+ * (none lent) so vultus-core stays framework-neutral; vultus-antd's `VultusProvider` merges
6
+ * in whatever an app passes as `components`.
7
+ */
8
+ export const VultusComponentsContext = createContext({});
9
+ export function useVultusComponents() {
10
+ return useContext(VultusComponentsContext);
11
+ }
12
+ /** The scope path (segment names, outermost first) that `useSpinnerKey` prefixes onto local keys. */
13
+ const SpinnerScopeContext = createContext([]);
14
+ /** Prefixes every spinner key below with `name` (scopes nest: outer/inner). */
15
+ export function SpinnerScope({ name, children }) {
16
+ const outer = useContext(SpinnerScopeContext);
17
+ // Memoized so consumers below (useSpinnerKey, via SpinnerScopeContext) don't re-render
18
+ // on every SpinnerScope re-render — only when the scope path actually changes. Matters
19
+ // once whole conversation views sit inside a SpinnerScope.
20
+ const scope = useMemo(() => [...outer, name], [outer, name]);
21
+ return _jsx(SpinnerScopeContext.Provider, { value: scope, children: children });
22
+ }
23
+ /** The scoped key for a library-local key: 'outer/inner/local', or 'local' outside any scope. */
24
+ export function useSpinnerKey(localKey) {
25
+ const scope = useContext(SpinnerScopeContext);
26
+ return [...scope, localKey].join('/');
27
+ }
28
+ //# sourceMappingURL=Components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Components.js","sourceRoot":"","sources":["../src/Components.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAsC,MAAM,OAAO,CAAC;AAkB/F;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,aAAa,CAAmB,EAAE,CAAC,CAAC;AAE3E,MAAM,UAAU,mBAAmB;IACjC,OAAO,UAAU,CAAC,uBAAuB,CAAC,CAAC;AAC7C,CAAC;AAED,qGAAqG;AACrG,MAAM,mBAAmB,GAAG,aAAa,CAAW,EAAE,CAAC,CAAC;AAExD,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,EAAE,IAAI,EAAE,QAAQ,EAA0C;IACrF,MAAM,KAAK,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC;IAC9C,uFAAuF;IACvF,uFAAuF;IACvF,2DAA2D;IAC3D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7D,OAAO,KAAC,mBAAmB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAgC,CAAC;AAC/F,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,MAAM,KAAK,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -12,4 +12,5 @@ export { useMixedBoolField, aggregateBool, type MixedBool, type MixedBoolFieldCo
12
12
  export { useOneOfField, type OneOfChoice, type OneOfChoiceControls, type OneOfFieldControls, type OneOfFieldOptions, } from './useOneOfField.js';
13
13
  export { InternalLinkContext, useInternalLink, type InternalLinkComponent } from './LinkContext.js';
14
14
  export { MessageSinkContext, useMessageSink, type MessageSink } from './MessageSink.js';
15
+ export { VultusComponentsContext, useVultusComponents, SpinnerScope, useSpinnerKey, type VultusComponents, type SpinnerProps, type SpinnerComponent, } from './Components.js';
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAClE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,KAAK,QAAQ,GACjH,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,EACL,iBAAiB,EAAE,aAAa,EAAE,KAAK,SAAS,EAAE,KAAK,sBAAsB,EAAE,KAAK,qBAAqB,GAC1G,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,GAC3G,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAClE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,KAAK,QAAQ,GACjH,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,EACL,iBAAiB,EAAE,aAAa,EAAE,KAAK,SAAS,EAAE,KAAK,sBAAsB,EAAE,KAAK,qBAAqB,GAC1G,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,GAC3G,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACxF,OAAO,EACL,uBAAuB,EAAE,mBAAmB,EAAE,YAAY,EAAE,aAAa,EACzE,KAAK,gBAAgB,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,GAChE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -12,4 +12,5 @@ export { useMixedBoolField, aggregateBool, } from './useMixedBoolField.js';
12
12
  export { useOneOfField, } from './useOneOfField.js';
13
13
  export { InternalLinkContext, useInternalLink } from './LinkContext.js';
14
14
  export { MessageSinkContext, useMessageSink } from './MessageSink.js';
15
+ export { VultusComponentsContext, useVultusComponents, SpinnerScope, useSpinnerKey, } from './Components.js';
15
16
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,GAEnE,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAiD,MAAM,mBAAmB,CAAC;AAChG,OAAO,EACL,iBAAiB,EAAE,aAAa,GACjC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,aAAa,GACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAA8B,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAoB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,GAEnE,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAiD,MAAM,mBAAmB,CAAC;AAChG,OAAO,EACL,iBAAiB,EAAE,aAAa,GACjC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,aAAa,GACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAA8B,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAoB,MAAM,kBAAkB,CAAC;AACxF,OAAO,EACL,uBAAuB,EAAE,mBAAmB,EAAE,YAAY,EAAE,aAAa,GAE1E,MAAM,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vultus-core",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Framework-neutral action model + hooks for vultus (antd-free by design)",
6
6
  "repository": {
@@ -0,0 +1,47 @@
1
+ import { createContext, useContext, useMemo, type ComponentType, type ReactNode } from 'react';
2
+
3
+ /** A spinner an app lends to vultus/optio, rendered in place of their native loading indicators. */
4
+ export interface SpinnerProps {
5
+ /** The spinner's identity: stable across re-renders and remounts, unique on the page (after scoping). */
6
+ spinnerKey: string;
7
+ /** antd's names (the height of antd's Spin indicator) or a height in px. */
8
+ size?: 'small' | 'default' | 'large' | number;
9
+ /** Accessible label; the spinner's own default when omitted. */
10
+ label?: string;
11
+ }
12
+ export type SpinnerComponent = ComponentType<SpinnerProps>;
13
+
14
+ /** Components an app lends to the libraries. */
15
+ export interface VultusComponents {
16
+ Spinner?: SpinnerComponent;
17
+ }
18
+
19
+ /**
20
+ * The components an app lends to vultus/optio in place of their own UI. Default is `{}`
21
+ * (none lent) so vultus-core stays framework-neutral; vultus-antd's `VultusProvider` merges
22
+ * in whatever an app passes as `components`.
23
+ */
24
+ export const VultusComponentsContext = createContext<VultusComponents>({});
25
+
26
+ export function useVultusComponents(): VultusComponents {
27
+ return useContext(VultusComponentsContext);
28
+ }
29
+
30
+ /** The scope path (segment names, outermost first) that `useSpinnerKey` prefixes onto local keys. */
31
+ const SpinnerScopeContext = createContext<string[]>([]);
32
+
33
+ /** Prefixes every spinner key below with `name` (scopes nest: outer/inner). */
34
+ export function SpinnerScope({ name, children }: { name: string; children?: ReactNode }) {
35
+ const outer = useContext(SpinnerScopeContext);
36
+ // Memoized so consumers below (useSpinnerKey, via SpinnerScopeContext) don't re-render
37
+ // on every SpinnerScope re-render — only when the scope path actually changes. Matters
38
+ // once whole conversation views sit inside a SpinnerScope.
39
+ const scope = useMemo(() => [...outer, name], [outer, name]);
40
+ return <SpinnerScopeContext.Provider value={scope}>{children}</SpinnerScopeContext.Provider>;
41
+ }
42
+
43
+ /** The scoped key for a library-local key: 'outer/inner/local', or 'local' outside any scope. */
44
+ export function useSpinnerKey(localKey: string): string {
45
+ const scope = useContext(SpinnerScopeContext);
46
+ return [...scope, localKey].join('/');
47
+ }
package/src/index.ts CHANGED
@@ -19,3 +19,7 @@ export {
19
19
  } from './useOneOfField.js';
20
20
  export { InternalLinkContext, useInternalLink, type InternalLinkComponent } from './LinkContext.js';
21
21
  export { MessageSinkContext, useMessageSink, type MessageSink } from './MessageSink.js';
22
+ export {
23
+ VultusComponentsContext, useVultusComponents, SpinnerScope, useSpinnerKey,
24
+ type VultusComponents, type SpinnerProps, type SpinnerComponent,
25
+ } from './Components.js';