@webority/ui-react 0.54.0 → 0.55.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/dist/components/AppAutocomplete.js +1 -1
- package/dist/components/AppMultiSelect.js +1 -1
- package/dist/components/AppSelect.js +1 -1
- package/dist/components/AppSelectMini.js +1 -1
- package/dist/components/AppTour.js +1 -1
- package/dist/types/components/AppAutocomplete.d.ts +9 -2
- package/dist/types/components/AppMultiSelect.d.ts +4 -1
- package/dist/types/components/AppTour.d.ts +35 -10
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"./warnInvalidValue.js";import t from"./warnUnknownProps.js";import n from"./AppInfoTip.js";import r from"./AppRequiredMark.js";import i,{optionsEqual as
|
|
1
|
+
import e from"./warnInvalidValue.js";import t from"./warnUnknownProps.js";import n from"./AppInfoTip.js";import r from"./AppRequiredMark.js";import i from"./useNodeLabels.js";import a,{optionsEqual as o}from"./useWuiControl.js";import{forwardRef as s,useEffect as c,useId as l,useRef as u}from"react";import{jsx as d,jsxs as f}from"react/jsx-runtime";import"@webority/ui-elements/elements/autocomplete";var p=[`sm`,`lg`],m=[],h=(e,t)=>({...e,label:t}),g=s(function({value:s,onChange:g,options:_,loadOptions:v,placeholder:y=`Search…`,minChars:b,debounce:x,disabled:S=!1,size:C,allowCustom:w=!1,name:T,id:E,label:D,error:O,hint:k,required:A=!1,help:j,helpLabel:M=`More information`,fieldClassName:N=``,...P},F){t(`AppAutocomplete`,P),e(`AppAutocomplete`,`size`,C,p);let I=typeof v==`function`,L=l(),R=E||L,{setRef:z,innerRef:B}=a({ref:F,value:s??``,on:{change:e=>g?.(e.currentTarget.value,{isCustom:!!e.detail?.isCustom})}}),V=_||m,{portal:H,toElementOptions:U}=i(V),W=u(!1);return c(()=>{let e=B.current;if(!e||I&&W.current)return;let t=U(V,h);o(t,e.options)||(e.options=t)},[V,I,B,U]),c(()=>{let e=B.current;if(!e||!I)return;let t=0,n=null,r=async r=>{let i=++t;n?.abort(),n=typeof AbortController==`function`?new AbortController:null,e.loading=!0;try{let a=await v(r.detail.query,{signal:n?.signal});i===t&&(W.current=!0,e.options=a||[])}catch{i===t&&(W.current=!0,e.options=[])}finally{i===t&&(e.loading=!1)}};return e.addEventListener(`search`,r),()=>{t=-1,n?.abort(),e.removeEventListener(`search`,r),e.loading=!1}},[I,v,B]),f(`div`,{className:`field${N?` ${N}`:``}`,children:[D&&f(`label`,{className:`label`,htmlFor:R,children:[D,A&&d(r,{}),j&&d(n,{label:M,children:j})]}),d(`wui-autocomplete`,{"aria-label":typeof D==`string`?D:void 0,"aria-describedby":O?`${R}-error`:k?`${R}-hint`:void 0,"aria-invalid":O?`true`:void 0,id:R,ref:z,name:T,placeholder:y,remote:I?``:void 0,"min-chars":b==null?void 0:String(b),debounce:x==null?void 0:String(x),size:C||void 0,"allow-custom":w?``:void 0,disabled:S?``:void 0,required:A?``:void 0,...P}),H,O?d(`div`,{className:`field-error`,id:`${R}-error`,children:O}):k?d(`div`,{className:`field-hint`,id:`${R}-hint`,children:k}):null]})});export{g as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"./warnInvalidValue.js";import t from"./warnUnknownProps.js";import n from"./AppInfoTip.js";import r from"./AppRequiredMark.js";import i,{optionsEqual as
|
|
1
|
+
import e from"./warnInvalidValue.js";import t from"./warnUnknownProps.js";import n from"./AppInfoTip.js";import r from"./AppRequiredMark.js";import i from"./useNodeLabels.js";import a,{optionsEqual as o,readValues as s,writeValues as c}from"./useWuiControl.js";import{forwardRef as l,useEffect as u,useId as d}from"react";import{jsx as f,jsxs as p}from"react/jsx-runtime";import"@webority/ui-elements/elements/multiselect";var m=[`sm`,`lg`],h=[],g=(e,t)=>({...e,label:t}),_=l(function({values:l,onChange:_,options:v,placeholder:y=`Select…`,searchPlaceholder:b=`Search…`,searchable:x=!0,disabled:S=!1,icon:C,size:w,collapseChips:T=!1,allowCustom:E=!1,validateCustom:D,customPattern:O,customInvalidMessage:k,name:A,id:j,label:M,error:N,hint:P,required:F=!1,help:I,helpLabel:L=`More information`,fieldClassName:R=``,...z},B){t(`AppMultiSelect`,z),e(`AppMultiSelect`,`size`,w,m);let V=d(),H=j||V,{setRef:U,innerRef:W}=a({ref:B,value:l,onChange:_,readValue:s,writeValue:c}),G=v||h,{portal:K,toElementOptions:q}=i(G);return u(()=>{let e=W.current;if(!e)return;let t=q(G,g);o(t,e.options)||(e.options=t)},[G,W,q]),u(()=>{let e=W.current;e&&(e.validateCustom=D??null)},[D,W]),p(`div`,{className:`field${R?` ${R}`:``}`,children:[M&&p(`label`,{className:`label`,htmlFor:H,children:[M,F&&f(r,{}),I&&f(n,{label:L,children:I})]}),f(`wui-multiselect`,{"aria-label":typeof M==`string`?M:void 0,"aria-describedby":N?`${H}-error`:P?`${H}-hint`:void 0,"aria-invalid":N?`true`:void 0,id:H,ref:U,name:A,placeholder:y,"search-placeholder":b,icon:C||void 0,size:w||void 0,"collapse-chips":T?``:void 0,"allow-custom":E?``:void 0,"custom-pattern":O||void 0,"custom-invalid-message":k||void 0,searchable:x?``:void 0,disabled:S?``:void 0,required:F?``:void 0,...z}),K,N?f(`div`,{className:`field-error`,id:`${H}-error`,children:N}):P?f(`div`,{className:`field-hint`,id:`${H}-hint`,children:P}):null]})});export{_ as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"./warnInvalidValue.js";import t from"./warnUnknownProps.js";import ee from"./AppInfoTip.js";import n from"./AppRequiredMark.js";import r
|
|
1
|
+
import e from"./warnInvalidValue.js";import t from"./warnUnknownProps.js";import ee from"./AppInfoTip.js";import n from"./AppRequiredMark.js";import r from"./useNodeLabels.js";import i,{optionsEqual as a}from"./useWuiControl.js";import{forwardRef as o,useEffect as s,useId as c,useRef as l}from"react";import{Fragment as u,jsx as d,jsxs as f}from"react/jsx-runtime";import"@webority/ui-elements/elements/select";var p=[`sm`,`lg`],m=(e,t)=>({value:e.value,label:t,icon:e.icon}),h=o(function({value:o,onChange:h,options:g=[],placeholder:_=`Select...`,searchPlaceholder:v=`Search...`,searchable:y=!1,clearable:b=!1,size:x,icon:S,prefix:C,suffix:w,floatingLabel:T=!1,disabled:E,label:D,required:O=!1,error:k,hint:A,help:j,helpLabel:M=`More information`,id:N,name:P,className:F=``,fieldClassName:I=``,"aria-label":L,"aria-labelledby":R,"aria-describedby":z,...B},V){t(`AppSelect`,B),e(`AppSelect`,`size`,x,p);let H=c(),{setRef:U,innerRef:W}=i({ref:V,value:o??``,onChange:h}),{portal:G,toElementOptions:K}=r(g),q=l({el:null,options:null});s(()=>{let e=W.current;if(!e||q.current.el===e&&q.current.options===g)return;q.current={el:e,options:g};let t=K(g,m);a(t,e.options)||(e.options=t)});let J=N||H,Y=T&&D,X=k&&J?`${J}-error`:void 0,Z=A&&J?`${J}-hint`:void 0,Q=f(u,{children:[d(`wui-select`,{"aria-label":L||(typeof D==`string`?D:void 0),"aria-labelledby":R||void 0,"aria-describedby":X||Z||z||void 0,"aria-invalid":k?`true`:void 0,ref:U,id:J,name:P,placeholder:T&&D?` `:_,"search-placeholder":v,searchable:y?``:void 0,clearable:b?``:void 0,size:x||void 0,icon:S||void 0,disabled:E?``:void 0,required:O?``:void 0,className:F||void 0,...B}),G]}),$=!Y&&(C!=null||w!=null)?f(`div`,{className:`input-affixed`,children:[C!=null&&d(`span`,{className:`affix affix-pre`,children:C}),Q,w!=null&&d(`span`,{className:`affix affix-suf`,children:w})]}):Q;return!D&&!k&&!A?$:f(`div`,{className:[`field`,I].filter(Boolean).join(` `),children:[D&&!Y&&f(`label`,{className:`label`,htmlFor:J,children:[D,O&&d(n,{}),j&&d(ee,{label:M,children:j})]}),Y?f(`div`,{className:`field-float`,children:[Q,f(`label`,{className:`float-label`,htmlFor:J,children:[D,O&&d(n,{})]})]}):$,k?d(`div`,{className:`field-error`,id:X,children:k}):A?d(`div`,{className:`field-hint`,id:Z,children:A}):null]})});export{h as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"./warnInvalidValue.js";import t from"./warnUnknownProps.js";import n
|
|
1
|
+
import e from"./warnInvalidValue.js";import t from"./warnUnknownProps.js";import n from"./useNodeLabels.js";import r,{optionsEqual as i}from"./useWuiControl.js";import{useEffect as a}from"react";import{Fragment as o,jsx as s,jsxs as c}from"react/jsx-runtime";import"@webority/ui-elements/elements/select";var l=[`sm`,`lg`],u=(e,t)=>({value:e.value,label:t,icon:e.icon});function d({value:d,onChange:f,options:p=[],placeholder:m=`Select...`,name:h,ariaLabel:g,id:_,disabled:v,size:y,icon:b,prefix:x,className:S,...C}){t(`AppSelectMini`,C),e(`AppSelectMini`,`size`,y,l);let{setRef:w,innerRef:T}=r({value:d??``,onChange:f}),{portal:E,toElementOptions:D}=n(p);return a(()=>{let e=T.current;if(!e)return;let t=D(p,u);i(t,e.options)||(e.options=t)},[p,T,D]),a(()=>{let e=T.current;if(e)for(let[t,n]of[[`icon`,b],[`prefix`,x]])n==null||n===``?e.removeAttribute(t):e.setAttribute(t,n)},[b,x,T]),c(o,{children:[s(`wui-select`,{ref:w,name:h,compact:``,id:_,placeholder:m,"aria-label":g,size:y||void 0,disabled:v?``:void 0,className:S,...C}),E]})}export{d as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"./warnUnknownProps.js";import"@webority/ui-elements/elements/tour";import{forwardRef as
|
|
1
|
+
import e from"./warnInvalidValue.js";import t from"./warnUnknownProps.js";import"@webority/ui-elements/elements/tour";import{forwardRef as n,useEffect as r,useLayoutEffect as i,useRef as a}from"react";import{jsx as o}from"react/jsx-runtime";var s=[`image`,`video`],c=[`click`],l=n(function({open:n,onClose:l,tourId:u,steps:d,seenStore:f,onBeforeStep:p,labels:m,endDialog:h=!0,className:g,..._},v){t(`AppTour`,_);for(let t of d)e(`AppTour`,`steps[].mediaType`,t.mediaType,s),e(`AppTour`,`steps[].advanceOn`,t.advanceOn,c);let y=a(null),b=e=>{y.current=e,typeof v==`function`?v(e):v&&(v.current=e)};i(()=>{let e=y.current;e.seenStore=f??null,e.onBeforeStep=p??null}),i(()=>{let e=y.current;n?e.setAttribute(`open`,``):e.removeAttribute(`open`)},[n]);let x=a(l);return x.current=l,r(()=>{let e=y.current,t=e=>{let{reason:t,index:n,position:r,total:i}=e.detail;x.current?.(t,{index:n,position:r,total:i})};return e.addEventListener(`wui-tour:close`,t),()=>e.removeEventListener(`wui-tour:close`,t)},[]),o(`wui-tour`,{ref:b,"tour-id":u,"back-label":m?.back,"next-label":m?.next,"skip-label":m?.skip,"done-label":m?.done,"progress-label":m?.progress,"advance-label":m?.advance,"media-pause-label":m?.mediaPause,"media-play-label":m?.mediaPlay,"end-title":m?.endTitle,"end-message":m?.endMessage,"end-button":m?.endButton,"end-dialog":h===!1?`false`:void 0,class:g||void 0,..._,children:d.map(e=>o(`wui-tour-step`,{target:e.target,title:e.title,media:e.media,"media-alt":e.mediaAlt,"media-poster":e.mediaPoster,"media-type":e.mediaType,"advance-on":e.advanceOn,"action-label":e.actionLabel,children:e.description},`${e.target}|${e.description}`))})});export{l as default};
|
|
@@ -6,18 +6,25 @@ import "@webority/ui-elements/elements/autocomplete";
|
|
|
6
6
|
* - **static** — pass `options` (`[{ value, label }]`); filtering is client-side.
|
|
7
7
|
* - **remote** — pass an async `loadOptions(query) => Promise<options>`; the field
|
|
8
8
|
* debounces typing, shows a spinner while your promise is in flight, then lists the
|
|
9
|
-
* results. You own the fetch; the component owns the UX.
|
|
9
|
+
* results. You own the fetch; the component owns the UX. `options` given alongside it
|
|
10
|
+
* are the list shown until the first load result arrives, which replaces them.
|
|
10
11
|
*
|
|
11
12
|
* @param {object} props
|
|
12
13
|
* @param {string} [props.value] Selected option value.
|
|
13
14
|
* @param {(value: string, meta?: { isCustom: boolean }) => void} [props.onChange] The second
|
|
14
15
|
* argument reports whether the commit was a freeform entry (`allowCustom`) rather than a
|
|
15
16
|
* listed option — existing callers reading only the first argument are unaffected.
|
|
16
|
-
* @param {{value: string, label:
|
|
17
|
+
* @param {Array<{ value: string, label: import('react').ReactNode }>} [props.options] Static options,
|
|
18
|
+
* or with `loadOptions` the initial list: shown before any load result arrives (and resolving a
|
|
19
|
+
* pre-filled value's label), then replaced by the first result; later changes are ignored.
|
|
20
|
+
* A label may be a node (`<>CO<sub>2</sub></>`): it renders as static markup in the menu, the
|
|
21
|
+
* input shows its text once chosen, and filtering and the option's accessible name use that
|
|
22
|
+
* text. Remote results from `loadOptions` take string labels only.
|
|
17
23
|
* @param {(query: string, opts?: { signal?: AbortSignal }) => Promise<{value: string, label: string}[]>} [props.loadOptions]
|
|
18
24
|
* Remote loader; receives an AbortSignal for the superseded request (optional to use).
|
|
19
25
|
* @param {string} [props.placeholder]
|
|
20
26
|
* @param {number} [props.minChars] Min chars before a remote search fires (default 1 in remote mode).
|
|
27
|
+
* 0 is allowed: opening the field with an empty box calls `loadOptions("")` for the first page.
|
|
21
28
|
* @param {number} [props.debounce] Debounce ms for remote search (default 250).
|
|
22
29
|
* @param {boolean} [props.disabled]
|
|
23
30
|
* @param {'sm'|'lg'} [props.size] Control size around the default.
|
|
@@ -17,7 +17,10 @@ import "@webority/ui-elements/elements/multiselect";
|
|
|
17
17
|
* @param {object} props
|
|
18
18
|
* @param {string[]} [props.values] Selected option values.
|
|
19
19
|
* @param {(values: string[]) => void} [props.onChange]
|
|
20
|
-
* @param {{value: string, label:
|
|
20
|
+
* @param {Array<{ value: string, label: import('react').ReactNode, description?: string, avatar?: string, initials?: string, disabled?: boolean, disabledHint?: string }>} [props.options]
|
|
21
|
+
* The choices. A label may be a node (`<>CO<sub>2</sub></>`): it renders as static markup in the
|
|
22
|
+
* menu and on the chosen chip, and search, typeahead and the accessible names (the option and the
|
|
23
|
+
* chip's remove button) use its text.
|
|
21
24
|
* @param {string} [props.placeholder]
|
|
22
25
|
* @param {string} [props.searchPlaceholder] Placeholder for the in-menu search box.
|
|
23
26
|
* @param {boolean} [props.searchable=true] Ignored under `allowCustom`, whose inline input is the search.
|
|
@@ -7,25 +7,50 @@ import "@webority/ui-elements/elements/tour";
|
|
|
7
7
|
*
|
|
8
8
|
* Accessibility: focus moves into the card on open, stays there while the tour runs, and returns
|
|
9
9
|
* to where it was on close; each step is announced; Escape skips the tour; the arrow keys move
|
|
10
|
-
* between steps. On a phone the card sits on the side of the
|
|
10
|
+
* between steps, except while focus is in a field. On a phone the card sits on the side of the
|
|
11
|
+
* target with room and never covers it. After the last step a closing dialog says the tour is
|
|
12
|
+
* done (`endDialog={false}` leaves it out); Escape there closes the tour as `finished`.
|
|
11
13
|
*
|
|
12
14
|
* Set `open` to run the tour and set it back to false from `onClose`. Pass a `seenStore` to
|
|
13
15
|
* remember that a person has seen it: it is asked before showing and written when the tour
|
|
14
|
-
* finishes or is skipped. `createLocalSeenStore()` (from
|
|
15
|
-
* the browser; a product that keeps it on its server
|
|
16
|
+
* finishes or is skipped, with that outcome. `createLocalSeenStore()` (from
|
|
17
|
+
* `@webority/ui-elements`) keeps that in the browser; a product that keeps it on its server
|
|
18
|
+
* passes its own `{ isSeen, markSeen }`.
|
|
19
|
+
*
|
|
20
|
+
* The element also raises bubbling events a product can listen for on the ref:
|
|
21
|
+
* `wui-tour:start` { total }, `wui-tour:step` { step, index, position, total } and
|
|
22
|
+
* `wui-tour:close` { reason, index, position, total, via }, where `via` is `button` or `escape`
|
|
23
|
+
* on a skip.
|
|
16
24
|
*
|
|
17
25
|
* @param {object} props
|
|
18
26
|
* @param {boolean} props.open Runs the tour. Set it back to false from `onClose`.
|
|
19
|
-
* @param {(reason: 'finished'|'skipped'|'alreadySeen'|'noTargets') => void} props.onClose
|
|
20
|
-
* `finished`: the person stepped past the last step; `skipped`: Skip
|
|
21
|
-
* seen); `alreadySeen`: the store says it was seen, so nothing showed;
|
|
22
|
-
* a visible target, so nothing showed (not marked seen).
|
|
27
|
+
* @param {(reason: 'finished'|'skipped'|'alreadySeen'|'noTargets', details: { index: number|null, position: number|null, total: number|null }) => void} props.onClose
|
|
28
|
+
* Called when the tour ends. `finished`: the person stepped past the last step; `skipped`: Skip
|
|
29
|
+
* or Escape (both marked seen); `alreadySeen`: the store says it was seen, so nothing showed;
|
|
30
|
+
* `noTargets`: no step had a visible target, so nothing showed (not marked seen). `details`
|
|
31
|
+
* names the step the tour ended on: its `index` in `steps`, and its `position` (from 1) out of
|
|
32
|
+
* `total`, counting only the steps that showed; all null for `alreadySeen` and `noTargets`.
|
|
23
33
|
* @param {string} props.tourId Names the tour in the seen store.
|
|
24
|
-
* @param {{ target: string, title?: string, description: string }[]} props.steps
|
|
25
|
-
*
|
|
34
|
+
* @param {{ target: string, title?: string, description: string, media?: string, mediaAlt?: string, mediaPoster?: string, mediaType?: 'image'|'video', advanceOn?: 'click', actionLabel?: string }[]} props.steps
|
|
35
|
+
* `target` is a CSS selector. `media` is the URL of an image or short loop shown above the
|
|
36
|
+
* title, `mediaAlt` its text alternative, `mediaPoster` the still a loop shows under reduced
|
|
37
|
+
* motion. `advanceOn: 'click'` moves the tour on when the person clicks the target, and the
|
|
38
|
+
* card says what to click; `actionLabel` names the control in that sentence, in place of the
|
|
39
|
+
* target's accessible name, which it falls back to.
|
|
40
|
+
* @param {{ isSeen: (tourId: string) => Promise<boolean>, markSeen: (tourId: string, outcome: 'finished'|'skipped') => Promise<void> }} [props.seenStore]
|
|
26
41
|
* Read through a ref, so an inline object does not restart a running tour.
|
|
27
42
|
* @param {(step: object, index: number) => void | Promise<void>} [props.onBeforeStep] Runs before each step's target is looked up, awaited. Use it to open a menu or switch a tab so the target is visible.
|
|
28
|
-
* @param {{ back?: string, next?: string, skip?: string, done?: string
|
|
43
|
+
* @param {{ back?: string, next?: string, skip?: string, done?: string, progress?: string, advance?: string, mediaPause?: string, mediaPlay?: string, endTitle?: string, endMessage?: string, endButton?: string }} [props.labels]
|
|
44
|
+
* Button text, defaults Back, Next, Skip, Done. `done` is the last step's button only with
|
|
45
|
+
* `endDialog={false}`; while the closing dialog is on, the last step reads `next`, because the
|
|
46
|
+
* dialog follows. `progress` is the step count template, default "Step {current} of {total}".
|
|
47
|
+
* `advance` is a click-to-advance step's sentence, default "Click {actionName} to continue.",
|
|
48
|
+
* where `{actionName}` is the step's `actionLabel` or else its target's accessible name.
|
|
49
|
+
* `mediaPause` and `mediaPlay` name a step loop's pause button while it plays and while it is
|
|
50
|
+
* paused, defaults "Pause animation" and "Play animation".
|
|
51
|
+
* `endTitle`, `endMessage` and `endButton` are the closing dialog's text, defaults "You're all
|
|
52
|
+
* set", a short friendly line, and "Done".
|
|
53
|
+
* @param {boolean} [props.endDialog=true] Show the closing dialog after the last step.
|
|
29
54
|
* @param {string} [props.className]
|
|
30
55
|
*/
|
|
31
56
|
declare const AppTour: import("react").ForwardRefExoticComponent<import("react").RefAttributes<any>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/ui-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.55.0",
|
|
4
4
|
"description": "Webority shared React component library — App* primitives on react-bootstrap + the @webority/theme design system.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
},
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@webority/theme": "0.
|
|
31
|
-
"@webority/ui-elements": "0.
|
|
30
|
+
"@webority/theme": "0.55.0",
|
|
31
|
+
"@webority/ui-elements": "0.55.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"@webority/analytics": "^0.21.0",
|