@cryptlex/web-components 6.6.6-alpha11 → 6.6.6-alpha13
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/autocomplete.d.ts +3 -0
- package/dist/components/autocomplete.js +2 -0
- package/dist/components/autocomplete.js.map +1 -0
- package/dist/components/id-search.js +1 -1
- package/dist/components/id-search.js.map +1 -1
- package/dist/components/numberfield.js +1 -1
- package/dist/components/select.js +1 -1
- package/dist/components/select.js.map +1 -1
- package/dist/components/table-of-contents.js +1 -1
- package/dist/components/table-of-contents.js.map +1 -1
- package/dist/utilities/form-context.d.ts +12 -1
- package/dist/utilities/form-context.js.map +1 -1
- package/dist/utilities/form-hook.d.ts +7 -0
- package/dist/utilities/form-hook.js.map +1 -1
- package/dist/utilities/form.d.ts +6 -1
- package/dist/utilities/form.js.map +1 -1
- package/dist/utilities/resources.js.map +1 -1
- package/lib/index.css +0 -12
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autocomplete.js","sources":["../../lib/components/autocomplete.tsx"],"sourcesContent":["import { Autocomplete as AriaAutoComplete } from 'react-aria-components';\n\n/** https://react-spectrum.adobe.com/react-aria/Autocomplete.html */\nexport const Autocomplete = AriaAutoComplete;\n"],"names":["Autocomplete","AriaAutoComplete"],"mappings":"qDAGO,MAAMA,EAAeC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as n,jsxs as c}from"react/jsx-runtime";import{useQuery as N}from"@tanstack/react-query";import{useId as b,useState as M}from"react";import{Autocomplete as x}from"react-aria-components";import{Button as F}from"./button.js";import{Loader as B}from"./loader.js";import{Menu as
|
|
1
|
+
import{jsx as n,jsxs as c}from"react/jsx-runtime";import{useQuery as N}from"@tanstack/react-query";import{useId as b,useState as M}from"react";import{Autocomplete as x}from"react-aria-components";import{Button as F}from"./button.js";import{Loader as B}from"./loader.js";import{Menu as w,MenuItem as j}from"./menu.js";import{PopoverTrigger as A,Popover as E}from"./popover.js";import{SearchField as K}from"./searchfield.js";import{getFieldErrorMessage as h}from"../utilities/form.js";import{useFieldContext as f}from"../utilities/form-context.js";import{FormField as L}from"./field.js";import"class-variance-authority";import"../utilities/theme.js";import"clsx";import"./icons.js";import"./list-box.js";import"./select.js";import"@tanstack/react-form";function p({label:r,description:t,errorMessage:e,searchFn:i,isDisabled:a,onBlur:g,onChange:q,value:s,renderLabel:S,...y}){const I=b(),[l,C]=M(""),{data:m,isError:d,isFetching:u,error:v}=N({queryKey:[I,l],queryFn:()=>i(l)});return n("div",{className:"group form-field",children:n(L,{label:r,description:t,errorMessage:e,children:c(A,{onOpenChange:o=>{o||g?.(s)},children:[n(F,{className:"min-w-3xs",isDisabled:a,children:S(s,m)}),n(E,{className:"w-auto min-w-[--trigger-width]",children:c(x,{inputValue:l,onInputChange:C,children:[n(K,{className:"mb-2",autoFocus:!0}),u&&n("div",{className:"p-input",children:n(B,{className:"mx-auto"})}),!u&&!d&&n(w,{...y,className:"max-h-48",items:m,renderEmptyState:()=>n("div",{className:"body-sm p-2",children:"No results found."}),children:o=>n(j,{id:o.id,children:o.name},o.id)}),d&&n("div",{className:"text-destructive p-icon body-sm",children:v.message})]})})]})})})}function T({...r}){return n(p,{selectedKeys:[r.value],onSelectionChange:t=>r.onChange(Array.from(t).filter(e=>typeof e=="string")[0]),renderLabel:(t,e)=>e?.find(i=>i.id===t)?.name??t,selectionMode:"single",...r})}function _({...r}){return n(p,{selectedKeys:r.value,onSelectionChange:t=>r.onChange(Array.from(t).filter(e=>typeof e=="string")),selectionMode:"multiple",renderLabel:(t,e)=>t.map(i=>e?.find(a=>a.id===i)?.name??i).join(","),...r})}function ne({isDisabled:r,...t}){const e=f({disabled:r});return n(T,{...t,isDisabled:r||e.form.state.isSubmitting,value:e.state.value,onBlur:i=>e.handleBlur(),onChange:i=>e.handleChange(i),errorMessage:h(e)})}function te({isDisabled:r,...t}){const e=f({disabled:r});return n(_,{...t,isDisabled:r||e.form.state.isSubmitting,value:e.state.value,onBlur:i=>e.handleBlur(),onChange:i=>e.handleChange(i),errorMessage:h(e)})}export{_ as MultipleIdSearchInput,T as SingleIdSearchInput,te as TfMultipleIdSearchInput,ne as TfSingleIdSearchInput};
|
|
2
2
|
//# sourceMappingURL=id-search.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id-search.js","sources":["../../lib/components/id-search.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query';\nimport { useId, useState } from 'react';\nimport { Autocomplete } from 'react-aria-components';\nimport { Button } from '../components/button';\nimport { Loader } from '../components/loader';\nimport { Menu, MenuItem } from '../components/menu';\nimport { Popover, PopoverTrigger } from '../components/popover';\nimport { SearchField } from '../components/searchfield';\nimport { getFieldErrorMessage } from '../utilities/form';\nimport { useFieldContext } from '../utilities/form-context';\nimport { FormField, type FormFieldProps } from './field';\n\n/**\n * Minimal resource shape used by the ID search inputs.\n * Only `id` and `name` are required.\n *\n * @example\n * const user: BaseSearchableResource = { id: 'u_123', name: 'Nabeel Farooq' };\n */\ntype BaseSearchableResource = {\n /** Unique identifier used as the input value. */\n id: string;\n /** Human-readable label shown to users. */\n name: string;\n};\n\n/**\n * - Generic, accessible ID-search building block.\n * - Search (powered by react-query)\n * - Renders an accessible Autocomplete + Menu listbox\n * - Exposes a controlled `value`/`onChange` contract so callers (and wrappers) can manage state\n * - Clear separation of concerns: this component only handles UI search/display; callers provide `searchFn`\n *\n * @template T - resource type extending `BaseSearchableResource` (must have `id` and `name`)\n * @template V - controlled value type (e.g. `string` for single-select or `string[]` for multi-select)\n *\n * @param props - props object (see inline property JSDoc for the most important fields)\n *\n * @remarks\n * - `searchFn` should return `Promise<T[] | undefined>`. Returning `undefined` indicates no results / handled error.\n * - When the popover closes, `onBlur` (if provided) is called with the current `value`.\n * - `renderLabel` must convert `value` to a readable string for the control button.\n *\n * @example\n * <BaseIdSearchInput\n * label=\"Owner\"\n * searchFn={q => api.searchUsers(q)}\n * value={ownerId}\n * onChange={setOwnerId}\n * renderLabel={(v, data) => data?.find(d => d.id === v)?.name ?? v}\n * />\n *\n * @testing\n * - Mock `searchFn` in unit tests; assert keyboard navigation, open/close behavior, and `onBlur` call on popover close.\n */\nfunction BaseIdSearchInput<T extends BaseSearchableResource, V>({\n label,\n description,\n errorMessage,\n searchFn,\n isDisabled,\n onBlur,\n onChange,\n value,\n renderLabel,\n ...props\n}: FormFieldProps & {\n /** Function that returns matching resources for the current query. */\n searchFn: (q: string) => Promise<T[] | undefined>;\n /** Disable interactions. */\n isDisabled?: boolean;\n /** Key used to access an alternate display accessor on item (kept for compatibility). */\n accessor: keyof BaseSearchableResource;\n /** Controlled value. */\n value: V;\n /** Called when popover closes or the field blurs with the current value. */\n onBlur?: (v: V) => void;\n /** Controlled change handler. */\n onChange: (v: V) => void;\n /** Render a human-readable label for the current value using the latest data. */\n renderLabel: (v: V, data: T[] | undefined) => string;\n} & Omit<React.ComponentProps<typeof Menu>, 'items' | 'className'>) {\n const id = useId();\n const [search, _setSearch] = useState('');\n const { data, isError, isFetching, error } = useQuery({\n queryKey: [id, search],\n queryFn: () => searchFn(search),\n });\n\n return (\n <div className=\"group form-field\">\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <PopoverTrigger\n onOpenChange={o => {\n if (!o) {\n // searchInputRef.current?.focus();\n onBlur?.(value);\n }\n }}\n >\n <Button className={'min-w-3xs'} isDisabled={isDisabled}>\n {renderLabel(value, data)}\n </Button>\n <Popover className={'p-2'}>\n <Autocomplete inputValue={search} onInputChange={_setSearch}>\n <SearchField className={'mb-2'} autoFocus />\n {isFetching && (\n <div className=\"p-input\">\n <Loader className=\"mx-auto\" />\n </div>\n )}\n {!isFetching && !isError && (\n <Menu\n {...props}\n className={'max-h-48'}\n items={data}\n renderEmptyState={() => <div className=\"body-sm p-2\">No results found.</div>}\n >\n {item => (\n <MenuItem key={item['id']} id={item['id']}>\n {item.name}\n </MenuItem>\n )}\n </Menu>\n )}\n {isError && <div className=\"text-destructive p-icon body-sm\">{error.message}</div>}\n </Autocomplete>\n </Popover>\n </PopoverTrigger>\n </FormField>\n </div>\n );\n}\n\n/**\n * Single-selection ID search input.\n *\n * Thin, typed wrapper around `BaseIdSearchInput` specialized for the very common single-ID case.\n * Adapts the internal selection events into `onChange(id?: string)` and renders the selected label.\n *\n * @template T - resource type (extends BaseSearchableResource)\n *\n * @param props - Inherits `BaseIdSearchInput` props but uses `string[]` value type.\n *\n * @example\n * <SingleIdSearchInput\n * label=\"Reporter\"\n * value={reporterId}\n * onChange={setReporterId}\n * searchFn={q => api.searchUsers(q)}\n * />\n *\n */\nexport function SingleIdSearchInput<T extends BaseSearchableResource>({\n ...props\n}: Omit<\n React.ComponentProps<typeof BaseIdSearchInput<T, string>>,\n 'onSelectionChange' | 'selectionMode' | 'selectedKeys' | 'renderLabel'\n>) {\n return (\n <BaseIdSearchInput\n selectedKeys={[props.value]}\n onSelectionChange={e => props.onChange(Array.from(e).filter(v => typeof v === 'string')[0])}\n renderLabel={(v, d) => d?.find(di => di.id === v)?.name ?? v}\n selectionMode=\"single\"\n {...props}\n />\n );\n}\n\n/**\n * Multi-selection ID search input.\n *\n * Thin wrapper around `BaseIdSearchInput` for the multiple-ID (`string[]`) case.\n * Adapts internal selection events into `onChange(ids: string[])`.\n *\n * @template T - resource type (extends BaseSearchableResource)\n *\n * @param props - Inherits `BaseIdSearchInput` props but uses `string[]` value type.\n *\n * @example\n * <MultipleIdSearchInput\n * label=\"Reviewers\"\n * value={reviewerIds}\n * onChange={setReviewerIds}\n * searchFn={q => api.searchUsers(q)}\n * />\n *\n * @remarks\n * - The `renderLabel` joins selected item names with commas for compact display.\n */\nexport function MultipleIdSearchInput<T extends BaseSearchableResource>({\n ...props\n}: Omit<\n React.ComponentProps<typeof BaseIdSearchInput<T, string[]>>,\n 'renderLabel' | 'onSelectionChange' | 'selectionMode' | 'selectedKeys'\n>) {\n return (\n <BaseIdSearchInput\n selectedKeys={props.value}\n onSelectionChange={e => props.onChange(Array.from(e).filter(v => typeof v === 'string'))}\n selectionMode=\"multiple\"\n renderLabel={(v, d) => v.map(vi => d?.find(di => di.id === vi)?.name ?? vi).join(',')}\n {...props}\n />\n );\n}\n\n/**\n * Form-integrated single-select ID input (field wrapper).\n *\n * Integrates `SingleIdSearchInput` into the form system using `useFieldContext`.\n * - wires `value`, `onChange`, and `onBlur`\n * - disables the control while the form is submitting\n * - surfaces field-level error messages\n *\n * @example\n * <TfSingleIdSearchInput name=\"ownerId\" label=\"Owner\" searchFn={q => api.searchUsers(q)} />\n \n */\nexport function TfSingleIdSearchInput({\n isDisabled,\n ...props\n}: Omit<React.ComponentProps<typeof SingleIdSearchInput>, 'value' | 'onChange'>) {\n const field = useFieldContext<string>({ disabled: isDisabled });\n return (\n <SingleIdSearchInput\n {...props}\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n onBlur={_ => field.handleBlur()}\n onChange={e => field.handleChange(e)}\n errorMessage={getFieldErrorMessage(field)}\n />\n );\n}\n// TODO, popover alignment should be same as Select\n\n/**\n * Form-integrated multi-select ID input (field wrapper).\n *\n * Integrates `MultipleIdSearchInput` into the form system using `useFieldContext`.\n * - wires `value`, `onChange`, and `onBlur`\n * - disables the control while the form is submitting\n * - surfaces field-level error messages\n *\n * @example\n * <TfMultipleIdSearchInput name=\"reviewerIds\" label=\"Reviewers\" searchFn={q => api.searchUsers(q)} />\n *\n */\nexport function TfMultipleIdSearchInput({\n isDisabled,\n ...props\n}: Omit<React.ComponentProps<typeof MultipleIdSearchInput>, 'value' | 'onChange'>) {\n const field = useFieldContext<string[]>({ disabled: isDisabled });\n return (\n <MultipleIdSearchInput\n {...props}\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n onBlur={_ => field.handleBlur()}\n onChange={e => field.handleChange(e)}\n errorMessage={getFieldErrorMessage(field)}\n />\n );\n}\n"],"names":["BaseIdSearchInput","label","description","errorMessage","searchFn","isDisabled","onBlur","onChange","value","renderLabel","props","id","useId","search","_setSearch","useState","data","isError","isFetching","error","useQuery","jsx","FormField","jsxs","PopoverTrigger","o","Button","Popover","Autocomplete","SearchField","Loader","Menu","item","MenuItem","SingleIdSearchInput","e","v","d","di","MultipleIdSearchInput","vi","TfSingleIdSearchInput","field","useFieldContext","_","getFieldErrorMessage","TfMultipleIdSearchInput"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"id-search.js","sources":["../../lib/components/id-search.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query';\nimport { useId, useState } from 'react';\nimport { Autocomplete } from 'react-aria-components';\nimport { Button } from '../components/button';\nimport { Loader } from '../components/loader';\nimport { Menu, MenuItem } from '../components/menu';\nimport { Popover, PopoverTrigger } from '../components/popover';\nimport { SearchField } from '../components/searchfield';\nimport { getFieldErrorMessage } from '../utilities/form';\nimport { useFieldContext } from '../utilities/form-context';\nimport { FormField, type FormFieldProps } from './field';\n\n/**\n * Minimal resource shape used by the ID search inputs.\n * Only `id` and `name` are required.\n *\n * @example\n * const user: BaseSearchableResource = { id: 'u_123', name: 'Nabeel Farooq' };\n */\ntype BaseSearchableResource = {\n /** Unique identifier used as the input value. */\n id: string;\n /** Human-readable label shown to users. */\n name: string;\n};\n\n/**\n * - Generic, accessible ID-search building block.\n * - Search (powered by react-query)\n * - Renders an accessible Autocomplete + Menu listbox\n * - Exposes a controlled `value`/`onChange` contract so callers (and wrappers) can manage state\n * - Clear separation of concerns: this component only handles UI search/display; callers provide `searchFn`\n *\n * @template T - resource type extending `BaseSearchableResource` (must have `id` and `name`)\n * @template V - controlled value type (e.g. `string` for single-select or `string[]` for multi-select)\n *\n * @param props - props object (see inline property JSDoc for the most important fields)\n *\n * @remarks\n * - `searchFn` should return `Promise<T[] | undefined>`. Returning `undefined` indicates no results / handled error.\n * - When the popover closes, `onBlur` (if provided) is called with the current `value`.\n * - `renderLabel` must convert `value` to a readable string for the control button.\n *\n * @example\n * <BaseIdSearchInput\n * label=\"Owner\"\n * searchFn={q => api.searchUsers(q)}\n * value={ownerId}\n * onChange={setOwnerId}\n * renderLabel={(v, data) => data?.find(d => d.id === v)?.name ?? v}\n * />\n *\n * @testing\n * - Mock `searchFn` in unit tests; assert keyboard navigation, open/close behavior, and `onBlur` call on popover close.\n */\nfunction BaseIdSearchInput<T extends BaseSearchableResource, V>({\n label,\n description,\n errorMessage,\n searchFn,\n isDisabled,\n onBlur,\n onChange,\n value,\n renderLabel,\n ...props\n}: FormFieldProps & {\n /** Function that returns matching resources for the current query. */\n searchFn: (q: string) => Promise<T[] | undefined>;\n /** Disable interactions. */\n isDisabled?: boolean;\n /** Key used to access an alternate display accessor on item (kept for compatibility). */\n accessor: keyof BaseSearchableResource;\n /** Controlled value. */\n value: V;\n /** Called when popover closes or the field blurs with the current value. */\n onBlur?: (v: V) => void;\n /** Controlled change handler. */\n onChange: (v: V) => void;\n /** Render a human-readable label for the current value using the latest data. */\n renderLabel: (v: V, data: T[] | undefined) => string;\n} & Omit<React.ComponentProps<typeof Menu>, 'items' | 'className'>) {\n const id = useId();\n const [search, _setSearch] = useState('');\n const { data, isError, isFetching, error } = useQuery({\n queryKey: [id, search],\n queryFn: () => searchFn(search),\n });\n\n return (\n <div className=\"group form-field\">\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <PopoverTrigger\n onOpenChange={o => {\n if (!o) {\n // searchInputRef.current?.focus();\n onBlur?.(value);\n }\n }}\n >\n <Button className={'min-w-3xs'} isDisabled={isDisabled}>\n {renderLabel(value, data)}\n </Button>\n <Popover className={'w-auto min-w-[--trigger-width]'}>\n <Autocomplete inputValue={search} onInputChange={_setSearch}>\n <SearchField className={'mb-2'} autoFocus />\n {isFetching && (\n <div className=\"p-input\">\n <Loader className=\"mx-auto\" />\n </div>\n )}\n {!isFetching && !isError && (\n <Menu\n {...props}\n className={'max-h-48'}\n items={data}\n renderEmptyState={() => <div className=\"body-sm p-2\">No results found.</div>}\n >\n {item => (\n <MenuItem key={item['id']} id={item['id']}>\n {item.name}\n </MenuItem>\n )}\n </Menu>\n )}\n {isError && <div className=\"text-destructive p-icon body-sm\">{error.message}</div>}\n </Autocomplete>\n </Popover>\n </PopoverTrigger>\n </FormField>\n </div>\n );\n}\n\n/**\n * Single-selection ID search input.\n *\n * Thin, typed wrapper around `BaseIdSearchInput` specialized for the very common single-ID case.\n * Adapts the internal selection events into `onChange(id?: string)` and renders the selected label.\n *\n * @template T - resource type (extends BaseSearchableResource)\n *\n * @param props - Inherits `BaseIdSearchInput` props but uses `string[]` value type.\n *\n * @example\n * <SingleIdSearchInput\n * label=\"Reporter\"\n * value={reporterId}\n * onChange={setReporterId}\n * searchFn={q => api.searchUsers(q)}\n * />\n *\n */\nexport function SingleIdSearchInput<T extends BaseSearchableResource>({\n ...props\n}: Omit<\n React.ComponentProps<typeof BaseIdSearchInput<T, string>>,\n 'onSelectionChange' | 'selectionMode' | 'selectedKeys' | 'renderLabel'\n>) {\n return (\n <BaseIdSearchInput\n selectedKeys={[props.value]}\n onSelectionChange={e => props.onChange(Array.from(e).filter(v => typeof v === 'string')[0])}\n renderLabel={(v, d) => d?.find(di => di.id === v)?.name ?? v}\n selectionMode=\"single\"\n {...props}\n />\n );\n}\n\n/**\n * Multi-selection ID search input.\n *\n * Thin wrapper around `BaseIdSearchInput` for the multiple-ID (`string[]`) case.\n * Adapts internal selection events into `onChange(ids: string[])`.\n *\n * @template T - resource type (extends BaseSearchableResource)\n *\n * @param props - Inherits `BaseIdSearchInput` props but uses `string[]` value type.\n *\n * @example\n * <MultipleIdSearchInput\n * label=\"Reviewers\"\n * value={reviewerIds}\n * onChange={setReviewerIds}\n * searchFn={q => api.searchUsers(q)}\n * />\n *\n * @remarks\n * - The `renderLabel` joins selected item names with commas for compact display.\n */\nexport function MultipleIdSearchInput<T extends BaseSearchableResource>({\n ...props\n}: Omit<\n React.ComponentProps<typeof BaseIdSearchInput<T, string[]>>,\n 'renderLabel' | 'onSelectionChange' | 'selectionMode' | 'selectedKeys'\n>) {\n return (\n <BaseIdSearchInput\n selectedKeys={props.value}\n onSelectionChange={e => props.onChange(Array.from(e).filter(v => typeof v === 'string'))}\n selectionMode=\"multiple\"\n renderLabel={(v, d) => v.map(vi => d?.find(di => di.id === vi)?.name ?? vi).join(',')}\n {...props}\n />\n );\n}\n\n/**\n * Form-integrated single-select ID input (field wrapper).\n *\n * Integrates `SingleIdSearchInput` into the form system using `useFieldContext`.\n * - wires `value`, `onChange`, and `onBlur`\n * - disables the control while the form is submitting\n * - surfaces field-level error messages\n *\n * @example\n * <TfSingleIdSearchInput name=\"ownerId\" label=\"Owner\" searchFn={q => api.searchUsers(q)} />\n \n */\nexport function TfSingleIdSearchInput({\n isDisabled,\n ...props\n}: Omit<React.ComponentProps<typeof SingleIdSearchInput>, 'value' | 'onChange'>) {\n const field = useFieldContext<string>({ disabled: isDisabled });\n return (\n <SingleIdSearchInput\n {...props}\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n onBlur={_ => field.handleBlur()}\n onChange={e => field.handleChange(e)}\n errorMessage={getFieldErrorMessage(field)}\n />\n );\n}\n\n/**\n * Form-integrated multi-select ID input (field wrapper).\n *\n * Integrates `MultipleIdSearchInput` into the form system using `useFieldContext`.\n * - wires `value`, `onChange`, and `onBlur`\n * - disables the control while the form is submitting\n * - surfaces field-level error messages\n *\n * @example\n * <TfMultipleIdSearchInput name=\"reviewerIds\" label=\"Reviewers\" searchFn={q => api.searchUsers(q)} />\n *\n */\nexport function TfMultipleIdSearchInput({\n isDisabled,\n ...props\n}: Omit<React.ComponentProps<typeof MultipleIdSearchInput>, 'value' | 'onChange'>) {\n const field = useFieldContext<string[]>({ disabled: isDisabled });\n return (\n <MultipleIdSearchInput\n {...props}\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n onBlur={_ => field.handleBlur()}\n onChange={e => field.handleChange(e)}\n errorMessage={getFieldErrorMessage(field)}\n />\n );\n}\n"],"names":["BaseIdSearchInput","label","description","errorMessage","searchFn","isDisabled","onBlur","onChange","value","renderLabel","props","id","useId","search","_setSearch","useState","data","isError","isFetching","error","useQuery","jsx","FormField","jsxs","PopoverTrigger","Button","Popover","Autocomplete","SearchField","Loader","Menu","item","MenuItem","SingleIdSearchInput","e","v","d","di","MultipleIdSearchInput","vi","TfSingleIdSearchInput","field","useFieldContext","_","getFieldErrorMessage","TfMultipleIdSearchInput"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as r,jsxs as d}from"react/jsx-runtime";import{NumberField as c,composeRenderProps as n,Input as p}from"react-aria-components";import{Button as f}from"./button.js";import{getFieldErrorMessage as l}from"../utilities/form.js";import{useFieldContext as b}from"../utilities/form-context.js";import{classNames as i}from"../utilities/theme.js";import{FormField as h,FieldGroup as N}from"./field.js";import{IcUp as g,IcDown as F}from"./icons.js";import"class-variance-authority";import"./loader.js";import"
|
|
1
|
+
import{jsx as r,jsxs as d}from"react/jsx-runtime";import{NumberField as c,composeRenderProps as n,Input as p}from"react-aria-components";import{Button as f}from"./button.js";import{getFieldErrorMessage as l}from"../utilities/form.js";import{useFieldContext as b}from"../utilities/form-context.js";import{classNames as i}from"../utilities/theme.js";import{FormField as h,FieldGroup as N}from"./field.js";import{IcUp as g,IcDown as F}from"./icons.js";import"class-variance-authority";import"./loader.js";import"clsx";import"react";import"@tanstack/react-form";const x=c;function v({className:o,...t}){return r(p,{className:n(o,e=>i("w-fit min-w-0 flex-1 border-r border-transparent bg-popover pr-2 outline-0 placeholder:text-muted-foreground [&::-webkit-search-cancel-button]:hidden",e)),...t})}function w({className:o,...t}){return d("div",{className:i("absolute right-0 flex h-full flex-col border-l",o),...t,children:[r(m,{slot:"increment",children:r(g,{"aria-hidden":!0,className:"size-icon"})}),r("div",{className:"border-b"}),r(m,{slot:"decrement",children:r(F,{"aria-hidden":!0,className:"size-icon"})})]})}function m({className:o,...t}){return r(f,{className:n(o,e=>i("w-auto grow h-3 px-0.5 text-muted-foreground",e)),variant:"ghost",size:"none",...t})}function I({label:o,description:t,errorMessage:e,className:s,...a}){return r(x,{className:n(s,u=>i("group form-field",u)),...a,children:r(h,{label:o,description:t,errorMessage:e,children:d(N,{children:[r(v,{}),r(w,{})]})})})}function T({isDisabled:o,...t}){const e=b({disabled:o});return r(I,{isInvalid:!!l(e),isDisabled:o||e.form.state.isSubmitting,value:e.state.value,id:e.name,onChange:e.handleChange,onBlur:e.handleBlur,errorMessage:l(e),...t})}export{I as NumberField,T as TfNumberField};
|
|
2
2
|
//# sourceMappingURL=numberfield.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{jsx as o,jsxs as c,Fragment as u}from"react/jsx-runtime";import{Select as p,composeRenderProps as i,SelectValue as f,ListBox as S}from"react-aria-components";import{Button as h}from"./button.js";import{FormField as g}from"./field.js";import{getFieldErrorMessage as x}from"../utilities/form.js";import{useFieldContext as B}from"../utilities/form-context.js";import{classNames as l}from"../utilities/theme.js";import{IcDown as N}from"./icons.js";import{ListBoxItem as w,ListBoxHeader as C,ListBoxCollection as F}from"./list-box.js";import{Popover as L}from"./popover.js";import"class-variance-authority";import"./loader.js";import"clsx";import"react";import"@tanstack/react-form";const
|
|
1
|
+
"use client";import{jsx as o,jsxs as c,Fragment as u}from"react/jsx-runtime";import{Select as p,composeRenderProps as i,SelectValue as f,ListBox as S}from"react-aria-components";import{Button as h}from"./button.js";import{FormField as g}from"./field.js";import{getFieldErrorMessage as x}from"../utilities/form.js";import{useFieldContext as B}from"../utilities/form-context.js";import{classNames as l}from"../utilities/theme.js";import{IcDown as N}from"./icons.js";import{ListBoxItem as w,ListBoxHeader as C,ListBoxCollection as F}from"./list-box.js";import{Popover as L}from"./popover.js";import"class-variance-authority";import"./loader.js";import"clsx";import"react";import"@tanstack/react-form";const b=p,v=w,Q=C,U=F,j=({className:r,...t})=>o(f,{className:i(r,e=>l("line-clamp-1 data-[placeholder]:text-muted-foreground","[&>[slot=description]]:hidden",e)),...t});function y({className:r,children:t,...e}){return o(h,{...e,className:"justify-between",children:i(t,n=>c(u,{children:[n,o(N,{"aria-hidden":"true",className:"opacity-50"})]}))})}function I({className:r,...t}){return o(L,{className:i(r,e=>l("w-auto min-w-[--trigger-width]",e)),...t})}function P({className:r,...t}){return o(S,{className:i(r,e=>l("overflow-auto p-1 outline-none",e)),...t})}function V({label:r,description:t,errorMessage:e,children:n,className:s,items:a,...m}){return o(b,{className:i(s,d=>l("group form-field",d)),...m,children:c(g,{label:r,description:t,errorMessage:e,children:[o(y,{children:o(j,{})}),o(I,{children:o(P,{items:a,children:n})})]})})}function W({...r}){const t=B({disabled:r.isDisabled});return o(V,{selectedKey:t.state.value,onSelectionChange:e=>t.handleChange(e.toString()),onBlur:t.handleBlur,errorMessage:x(t),...r,children:e=>o(v,{id:e.id,children:e.label},e.id)})}export{U as SelectCollection,Q as SelectHeader,v as SelectItem,I as SelectPopover,j as SelectValue,V as SingleSelect,W as TfSingleSelect};
|
|
2
2
|
//# sourceMappingURL=select.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.js","sources":["../../lib/components/select.tsx"],"sourcesContent":["'use client';\nimport {\n ListBox as AriaListBox,\n ListBoxProps as AriaListBoxProps,\n PopoverProps as AriaPopoverProps,\n Select as AriaSelect,\n SelectProps as AriaSelectProps,\n SelectValue as AriaSelectValue,\n SelectValueProps as AriaSelectValueProps,\n composeRenderProps,\n} from 'react-aria-components';\n\nimport { Button } from '../components/button';\nimport { FormField, type FormFieldProps } from '../components/field';\nimport type { SelectOption } from '../components/select-options';\nimport { getFieldErrorMessage } from '../utilities/form';\nimport { useFieldContext } from '../utilities/form-context';\nimport { classNames } from '../utilities/theme';\nimport { IcDown } from './icons';\nimport { ListBoxCollection, ListBoxHeader, ListBoxItem } from './list-box';\nimport { Popover } from './popover';\n\nconst ASelect = AriaSelect;\nexport const SelectItem = ListBoxItem;\nexport const SelectHeader = ListBoxHeader;\nexport const SelectCollection = ListBoxCollection;\n\nexport const SelectValue = <T extends object>({ className, ...props }: AriaSelectValueProps<T>) => (\n <AriaSelectValue\n className={composeRenderProps(className, className =>\n classNames(\n 'line-clamp-1 data-[placeholder]:text-muted-foreground',\n /* Description */\n '[&>[slot=description]]:hidden',\n className\n )\n )}\n {...props}\n />\n);\
|
|
1
|
+
{"version":3,"file":"select.js","sources":["../../lib/components/select.tsx"],"sourcesContent":["'use client';\nimport {\n ListBox as AriaListBox,\n ListBoxProps as AriaListBoxProps,\n PopoverProps as AriaPopoverProps,\n Select as AriaSelect,\n SelectProps as AriaSelectProps,\n SelectValue as AriaSelectValue,\n SelectValueProps as AriaSelectValueProps,\n composeRenderProps,\n} from 'react-aria-components';\n\nimport { Button } from '../components/button';\nimport { FormField, type FormFieldProps } from '../components/field';\nimport type { SelectOption } from '../components/select-options';\nimport { getFieldErrorMessage } from '../utilities/form';\nimport { useFieldContext } from '../utilities/form-context';\nimport { classNames } from '../utilities/theme';\nimport { IcDown } from './icons';\nimport { ListBoxCollection, ListBoxHeader, ListBoxItem } from './list-box';\nimport { Popover } from './popover';\n\nconst ASelect = AriaSelect;\nexport const SelectItem = ListBoxItem;\nexport const SelectHeader = ListBoxHeader;\nexport const SelectCollection = ListBoxCollection;\n\nexport const SelectValue = <T extends object>({ className, ...props }: AriaSelectValueProps<T>) => (\n <AriaSelectValue\n className={composeRenderProps(className, className =>\n classNames(\n 'line-clamp-1 data-[placeholder]:text-muted-foreground',\n /* Description */\n '[&>[slot=description]]:hidden',\n className\n )\n )}\n {...props}\n />\n);\nfunction SelectTrigger({ className, children, ...props }: React.ComponentProps<typeof Button>) {\n return (\n <Button {...props} className=\"justify-between\">\n {composeRenderProps(children, children => (\n <>\n {children}\n <IcDown aria-hidden=\"true\" className=\"opacity-50\" />\n </>\n ))}\n </Button>\n );\n}\n\nexport function SelectPopover({ className, ...props }: AriaPopoverProps) {\n return (\n <Popover\n className={composeRenderProps(className, className =>\n classNames('w-auto min-w-[--trigger-width]', className)\n )}\n {...props}\n />\n );\n}\n\nfunction SelectListBox<T extends object>({ className, ...props }: AriaListBoxProps<T>) {\n return (\n <AriaListBox\n className={composeRenderProps(className, className =>\n classNames('overflow-auto p-1 outline-none', className)\n )}\n {...props}\n />\n );\n}\n\nexport interface SingleSelectProps<T extends SelectOption>\n extends Omit<AriaSelectProps<T>, 'children'>,\n FormFieldProps {\n items: Iterable<T>;\n children: React.ReactNode | ((item: T) => React.ReactNode);\n}\n\nexport function SingleSelect<T extends SelectOption>({\n label,\n description,\n errorMessage,\n children,\n className,\n items,\n ...props\n}: SingleSelectProps<T>) {\n return (\n <ASelect\n className={composeRenderProps(className, className => classNames('group form-field', className))}\n {...props}\n >\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectPopover>\n <SelectListBox items={items}>{children}</SelectListBox>\n </SelectPopover>\n </FormField>\n </ASelect>\n );\n}\n\ntype TfSingleSelectProps<T extends SelectOption> = Omit<SingleSelectProps<T>, 'value' | 'setValue' | 'children'>;\n\nexport function TfSingleSelect<T extends SelectOption>({ ...props }: TfSingleSelectProps<T>) {\n const field = useFieldContext<string>({ disabled: props.isDisabled });\n\n return (\n <SingleSelect\n selectedKey={field.state.value}\n onSelectionChange={e => field.handleChange(e!.toString())}\n onBlur={field.handleBlur}\n errorMessage={getFieldErrorMessage(field)}\n {...props}\n >\n {item => (\n <SelectItem id={item.id} key={item.id}>\n {item.label}\n </SelectItem>\n )}\n </SingleSelect>\n );\n}\n"],"names":["ASelect","AriaSelect","SelectItem","ListBoxItem","SelectHeader","ListBoxHeader","SelectCollection","ListBoxCollection","SelectValue","className","props","jsx","AriaSelectValue","composeRenderProps","classNames","SelectTrigger","children","Button","jsxs","Fragment","IcDown","SelectPopover","Popover","SelectListBox","AriaListBox","SingleSelect","label","description","errorMessage","items","FormField","TfSingleSelect","field","useFieldContext","getFieldErrorMessage","item"],"mappings":"0rBAsBA,MAAMA,EAAUC,EACHC,EAAaC,EACbC,EAAeC,EACfC,EAAmBC,EAEnBC,EAAc,CAAmB,CAAE,UAAAC,EAAW,GAAGC,KAC1DC,EAACC,EAAA,CACG,UAAWC,EAAmBJ,EAAWA,GACrCK,EACI,wDAEA,gCACAL,CAAA,CACJ,EAEH,GAAGC,CAAA,CACR,EAEJ,SAASK,EAAc,CAAE,UAAAN,EAAW,SAAAO,EAAU,GAAGN,GAA8C,CAC3F,OACIC,EAACM,EAAA,CAAQ,GAAGP,EAAO,UAAU,kBACxB,SAAAG,EAAmBG,EAAUA,GAC1BE,EAAAC,EAAA,CACK,SAAA,CAAAH,EACDL,EAACS,EAAA,CAAO,cAAY,OAAO,UAAU,YAAA,CAAa,CAAA,CAAA,CACtD,CACH,CAAA,CACL,CAER,CAEO,SAASC,EAAc,CAAE,UAAAZ,EAAW,GAAGC,GAA2B,CACrE,OACIC,EAACW,EAAA,CACG,UAAWT,EAAmBJ,EAAWA,GACrCK,EAAW,iCAAkCL,CAAS,CAAA,EAEzD,GAAGC,CAAA,CAAA,CAGhB,CAEA,SAASa,EAAgC,CAAE,UAAAd,EAAW,GAAGC,GAA8B,CACnF,OACIC,EAACa,EAAA,CACG,UAAWX,EAAmBJ,EAAWA,GACrCK,EAAW,iCAAkCL,CAAS,CAAA,EAEzD,GAAGC,CAAA,CAAA,CAGhB,CASO,SAASe,EAAqC,CACjD,MAAAC,EACA,YAAAC,EACA,aAAAC,EACA,SAAAZ,EACA,UAAAP,EACA,MAAAoB,EACA,GAAGnB,CACP,EAAyB,CACrB,OACIC,EAACX,EAAA,CACG,UAAWa,EAAmBJ,EAAWA,GAAaK,EAAW,mBAAoBL,CAAS,CAAC,EAC9F,GAAGC,EAEJ,SAAAQ,EAACY,EAAA,CAAU,MAAAJ,EAAc,YAAAC,EAA0B,aAAAC,EAC/C,SAAA,CAAAjB,EAACI,EAAA,CACG,SAAAJ,EAACH,EAAA,CAAA,CAAY,EACjB,IACCa,EAAA,CACG,SAAAV,EAACY,EAAA,CAAc,MAAAM,EAAe,SAAAb,EAAS,CAAA,CAC3C,CAAA,CAAA,CACJ,CAAA,CAAA,CAGZ,CAIO,SAASe,EAAuC,CAAE,GAAGrB,GAAiC,CACzF,MAAMsB,EAAQC,EAAwB,CAAE,SAAUvB,EAAM,WAAY,EAEpE,OACIC,EAACc,EAAA,CACG,YAAaO,EAAM,MAAM,MACzB,kBAAmB,GAAKA,EAAM,aAAa,EAAG,UAAU,EACxD,OAAQA,EAAM,WACd,aAAcE,EAAqBF,CAAK,EACvC,GAAGtB,EAEH,SAAAyB,KACIjC,EAAA,CAAW,GAAIiC,EAAK,GAChB,SAAAA,EAAK,KAAA,EADoBA,EAAK,EAEnC,CAAA,CAAA,CAIhB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{jsxs as
|
|
1
|
+
"use client";import{jsxs as p,jsx as d}from"react/jsx-runtime";import{useMemo as h,useRef as f,useEffect as u,useState as v}from"react";import{classNames as g}from"../utilities/theme.js";import"clsx";function b(n){const[i,l]=v([]);return u(()=>{const o=new Set,s=new IntersectionObserver(r=>{for(const e of r)e.isIntersecting?o.add(e.target.id):o.delete(e.target.id);const t=n.filter(e=>o.has(e));l(t)},{rootMargin:"0% 0% -80% 0%"});for(const r of n??[]){const t=document.getElementById(r);t&&s.observe(t)}return()=>{for(const r of n??[]){const t=document.getElementById(r);t&&s.unobserve(t)}}},[n]),i}function N({toc:n,className:i}){const l=h(()=>n.map(e=>e.url.replace("#","")),[n]),o=b(l),s=o.length>0?o[0]:null,r=f({}),t=f(null);return u(()=>{if(s){const e=r.current[`#${s}`],c=t.current;if(e&&c){const a=e.offsetTop,m=c.clientHeight;c.scrollTo({top:a-m/2,behavior:"smooth"})}}},[s]),n.length?p("div",{ref:t,className:g(i),children:[d("p",{className:"text-muted opacity-70 mb-1 body-sm select-none",children:"On This Page"}),d("div",{className:"flex flex-col gap-1",children:n.map(e=>{const c=e.url.replace(/^#/,"");return d("a",{href:e.url,ref:a=>{r.current[e.url]=a},className:"text-muted-foreground hover:text-foreground data-[active=true]:text-foreground body-sm no-underline transition-colors data-[depth=3]:pl-4 data-[depth=4]:pl-6","data-active":o.includes(c),"data-depth":e.depth,children:e.title},e.url)})})]}):null}export{N as TableOfContents};
|
|
2
2
|
//# sourceMappingURL=table-of-contents.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-of-contents.js","sources":["../../lib/components/table-of-contents.tsx"],"sourcesContent":["'use client';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { classNames } from '../utilities/theme';\n\nfunction useActiveItem(itemIds: string[]) {\n const [
|
|
1
|
+
{"version":3,"file":"table-of-contents.js","sources":["../../lib/components/table-of-contents.tsx"],"sourcesContent":["'use client';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { classNames } from '../utilities/theme';\n\nfunction useActiveItem(itemIds: string[]) {\n const [activeIds, setActiveIds] = useState<string[]>([]);\n\n useEffect(() => {\n const intersectingIds = new Set<string>();\n\n const observer = new IntersectionObserver(\n entries => {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n intersectingIds.add(entry.target.id);\n } else {\n intersectingIds.delete(entry.target.id);\n }\n }\n\n // Convert to array and sort by document order\n const sortedActiveIds = itemIds.filter(id => intersectingIds.has(id));\n setActiveIds(sortedActiveIds);\n },\n { rootMargin: '0% 0% -80% 0%' }\n );\n\n for (const id of itemIds ?? []) {\n const element = document.getElementById(id);\n if (element) {\n observer.observe(element);\n }\n }\n\n return () => {\n for (const id of itemIds ?? []) {\n const element = document.getElementById(id);\n if (element) {\n observer.unobserve(element);\n }\n }\n };\n }, [itemIds]);\n\n return activeIds;\n}\n\nexport type TableOfContentsHeading = {\n title?: React.ReactNode;\n url: string;\n depth: number;\n};\n\nexport function TableOfContents({ toc, className }: { toc: TableOfContentsHeading[]; className?: string }) {\n const itemIds = useMemo(() => toc.map(item => item.url.replace('#', '')), [toc]);\n const activeIds = useActiveItem(itemIds);\n const firstActiveId = activeIds.length > 0 ? activeIds[0] : null;\n const linkRefs = useRef<Record<string, HTMLAnchorElement | null>>({});\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n // Scroll to first active item\n useEffect(() => {\n if (firstActiveId) {\n const activeEl = linkRefs.current[`#${firstActiveId}`];\n const containerEl = containerRef.current;\n\n if (activeEl && containerEl) {\n const linkTop = activeEl.offsetTop;\n const containerHeight = containerEl.clientHeight;\n containerEl.scrollTo({\n top: linkTop - containerHeight / 2,\n behavior: 'smooth',\n });\n }\n }\n }, [firstActiveId]);\n\n if (!toc.length) {\n return null;\n }\n\n return (\n <div ref={containerRef} className={classNames(className)}>\n <p className=\"text-muted opacity-70 mb-1 body-sm select-none\">On This Page</p>\n <div className=\"flex flex-col gap-1\">\n {toc.map(item => {\n const id = item.url.replace(/^#/, '');\n\n return (\n // It is okay to use plain <a hrefs> here because the links all point to IDs on the same page and does not impact any routers.\n <a\n key={item.url}\n href={item.url}\n ref={el => {\n linkRefs.current[item.url] = el;\n }}\n className=\"text-muted-foreground hover:text-foreground data-[active=true]:text-foreground body-sm no-underline transition-colors data-[depth=3]:pl-4 data-[depth=4]:pl-6\"\n data-active={activeIds.includes(id)}\n data-depth={item.depth}\n >\n {item.title}\n </a>\n );\n })}\n </div>\n </div>\n );\n}\n"],"names":["useActiveItem","itemIds","activeIds","setActiveIds","useState","useEffect","intersectingIds","observer","entries","entry","sortedActiveIds","id","element","TableOfContents","toc","className","useMemo","item","firstActiveId","linkRefs","useRef","containerRef","activeEl","containerEl","linkTop","containerHeight","classNames","jsx","el"],"mappings":"wMAIA,SAASA,EAAcC,EAAmB,CACtC,KAAM,CAACC,EAAWC,CAAY,EAAIC,EAAmB,CAAA,CAAE,EAEvD,OAAAC,EAAU,IAAM,CACZ,MAAMC,MAAsB,IAEtBC,EAAW,IAAI,qBACjBC,GAAW,CACP,UAAWC,KAASD,EACZC,EAAM,eACNH,EAAgB,IAAIG,EAAM,OAAO,EAAE,EAEnCH,EAAgB,OAAOG,EAAM,OAAO,EAAE,EAK9C,MAAMC,EAAkBT,EAAQ,UAAaK,EAAgB,IAAIK,CAAE,CAAC,EACpER,EAAaO,CAAe,CAChC,EACA,CAAE,WAAY,eAAA,CAAgB,EAGlC,UAAWC,KAAMV,GAAW,GAAI,CAC5B,MAAMW,EAAU,SAAS,eAAeD,CAAE,EACtCC,GACAL,EAAS,QAAQK,CAAO,CAEhC,CAEA,MAAO,IAAM,CACT,UAAWD,KAAMV,GAAW,GAAI,CAC5B,MAAMW,EAAU,SAAS,eAAeD,CAAE,EACtCC,GACAL,EAAS,UAAUK,CAAO,CAElC,CACJ,CACJ,EAAG,CAACX,CAAO,CAAC,EAELC,CACX,CAQO,SAASW,EAAgB,CAAE,IAAAC,EAAK,UAAAC,GAAoE,CACvG,MAAMd,EAAUe,EAAQ,IAAMF,EAAI,IAAIG,GAAQA,EAAK,IAAI,QAAQ,IAAK,EAAE,CAAC,EAAG,CAACH,CAAG,CAAC,EACzEZ,EAAYF,EAAcC,CAAO,EACjCiB,EAAgBhB,EAAU,OAAS,EAAIA,EAAU,CAAC,EAAI,KACtDiB,EAAWC,EAAiD,EAAE,EAC9DC,EAAeD,EAA8B,IAAI,EAmBvD,OAhBAf,EAAU,IAAM,CACZ,GAAIa,EAAe,CACf,MAAMI,EAAWH,EAAS,QAAQ,IAAID,CAAa,EAAE,EAC/CK,EAAcF,EAAa,QAEjC,GAAIC,GAAYC,EAAa,CACzB,MAAMC,EAAUF,EAAS,UACnBG,EAAkBF,EAAY,aACpCA,EAAY,SAAS,CACjB,IAAKC,EAAUC,EAAkB,EACjC,SAAU,QAAA,CACb,CACL,CACJ,CACJ,EAAG,CAACP,CAAa,CAAC,EAEbJ,EAAI,SAKJ,MAAA,CAAI,IAAKO,EAAc,UAAWK,EAAWX,CAAS,EACnD,SAAA,CAAAY,EAAC,IAAA,CAAE,UAAU,iDAAiD,SAAA,eAAY,IACzE,MAAA,CAAI,UAAU,sBACV,SAAAb,EAAI,IAAIG,GAAQ,CACb,MAAMN,EAAKM,EAAK,IAAI,QAAQ,KAAM,EAAE,EAEpC,OAEIU,EAAC,IAAA,CAEG,KAAMV,EAAK,IACX,IAAKW,GAAM,CACPT,EAAS,QAAQF,EAAK,GAAG,EAAIW,CACjC,EACA,UAAU,gKACV,cAAa1B,EAAU,SAASS,CAAE,EAClC,aAAYM,EAAK,MAEhB,SAAAA,EAAK,KAAA,EATDA,EAAK,GAAA,CAYtB,CAAC,CAAA,CACL,CAAA,EACJ,EA3BO,IA6Bf"}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Exports contexts and hooks used by all form-related field components.
|
|
3
|
+
*
|
|
4
|
+
* These contexts come from @tanstack/react-form's createFormHookContexts helper
|
|
5
|
+
* and provide a lightweight, strongly-typed way for nested field components
|
|
6
|
+
* (text inputs, selects, checkboxes, etc.) to access the current field
|
|
7
|
+
* and form instances.
|
|
8
|
+
*
|
|
9
|
+
* Usage example:
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { useFieldContext } from './form-context';
|
|
12
|
+
* const field = useFieldContext<MyFieldType>();
|
|
13
|
+
* ```
|
|
3
14
|
*/
|
|
4
15
|
declare const fieldContext: import('react').Context<import('@tanstack/react-form').AnyFieldApi>, formContext: import('react').Context<import('@tanstack/react-form').AnyFormApi>;
|
|
5
16
|
export { fieldContext, formContext };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-context.js","sources":["../../lib/utilities/form-context.tsx"],"sourcesContent":["import { createFormHookContexts } from '@tanstack/react-form';\nimport { useEffect } from 'react';\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"form-context.js","sources":["../../lib/utilities/form-context.tsx"],"sourcesContent":["import { createFormHookContexts } from '@tanstack/react-form';\nimport { useEffect } from 'react';\n\n/**\n * Exports contexts and hooks used by all form-related field components.\n *\n * These contexts come from @tanstack/react-form's createFormHookContexts helper\n * and provide a lightweight, strongly-typed way for nested field components\n * (text inputs, selects, checkboxes, etc.) to access the current field\n * and form instances.\n *\n * Usage example:\n * ```ts\n * import { useFieldContext } from './form-context';\n * const field = useFieldContext<MyFieldType>();\n * ```\n */\nconst { fieldContext, formContext, useFieldContext: _useFieldContext } = createFormHookContexts();\n\nexport { fieldContext, formContext };\n/**\n * Custom hook to handle disabled state for form fields\n * @param {boolean} disabled - The disabled prop passed to the component\n * @returns The field context with disabled state properly managed\n */\nexport function useFieldContext<T>({ disabled }: { disabled?: boolean }) {\n const field = _useFieldContext<T>();\n\n useEffect(() => {\n field.setMeta(meta => ({\n ...meta,\n disabled: !!disabled,\n }));\n }, [disabled, field]);\n\n return field;\n}\n"],"names":["fieldContext","formContext","_useFieldContext","createFormHookContexts","useFieldContext","disabled","field","useEffect","meta"],"mappings":"gGAiBA,KAAM,CAAE,aAAAA,EAAc,YAAAC,EAAa,gBAAiBC,CAAA,EAAqBC,EAAA,EAQlE,SAASC,EAAmB,CAAE,SAAAC,GAAoC,CACrE,MAAMC,EAAQJ,EAAA,EAEd,OAAAK,EAAU,IAAM,CACZD,EAAM,QAAQE,IAAS,CACnB,GAAGA,EACH,SAAU,CAAC,CAACH,CAAA,EACd,CACN,EAAG,CAACA,EAAUC,CAAK,CAAC,EAEbA,CACX"}
|
|
@@ -9,6 +9,13 @@ import { TfTextField } from '../components/textfield';
|
|
|
9
9
|
/**
|
|
10
10
|
* Builder for form logic and user interfaces
|
|
11
11
|
*/
|
|
12
|
+
/**
|
|
13
|
+
* A small builder that wires the form library to the concrete UI components used across the app.
|
|
14
|
+
* `createFormHook` returns a `useAppForm` hook which contains standard wiring and default components for
|
|
15
|
+
* fields and form-level controls.
|
|
16
|
+
*
|
|
17
|
+
* It exports only the `useAppForm` hook. Consumers (forms in codebase) call `useAppForm` to access the form API and default components.
|
|
18
|
+
*/
|
|
12
19
|
export declare const useAppForm: <TFormData, TOnMount extends import('@tanstack/react-form').FormValidateOrFn<TFormData> | undefined, TOnChange extends import('@tanstack/react-form').FormValidateOrFn<TFormData> | undefined, TOnChangeAsync extends import('@tanstack/react-form').FormAsyncValidateOrFn<TFormData> | undefined, TOnBlur extends import('@tanstack/react-form').FormValidateOrFn<TFormData> | undefined, TOnBlurAsync extends import('@tanstack/react-form').FormAsyncValidateOrFn<TFormData> | undefined, TOnSubmit extends import('@tanstack/react-form').FormValidateOrFn<TFormData> | undefined, TOnSubmitAsync extends import('@tanstack/react-form').FormAsyncValidateOrFn<TFormData> | undefined, TOnServer extends import('@tanstack/react-form').FormAsyncValidateOrFn<TFormData> | undefined, TSubmitMeta>(props: import('@tanstack/react-form').FormOptions<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnServer, TSubmitMeta>) => import('@tanstack/react-form').FormApi<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnServer, TSubmitMeta> & import('@tanstack/react-form').ReactFormApi<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnServer, TSubmitMeta> & NoInfer<{
|
|
13
20
|
readonly Button: typeof Button;
|
|
14
21
|
}> & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-hook.js","sources":["../../lib/utilities/form-hook.tsx"],"sourcesContent":["import { createFormHook } from '@tanstack/react-form';\nimport { Button } from '../components/button';\nimport { TfCheckbox } from '../components/checkbox';\nimport { TfMultiSelect } from '../components/multi-select';\nimport { TfNumberField } from '../components/numberfield';\nimport { TfSingleSelect } from '../components/select';\nimport { TfTextField } from '../components/textfield';\nimport { fieldContext, formContext } from '../utilities/form-context';\n\n/** Don't put this in the same file as form-context.tsx, this causes circular dependencies. */\n/** TODO, lazy loading when fieldComponents are large */\n/**\n * Builder for form logic and user interfaces\n */\nexport const { useAppForm } = createFormHook({\n fieldComponents: {\n TfTextField,\n TfNumberField,\n TfMultiSelect,\n TfSingleSelect,\n TfCheckbox,\n },\n formComponents: {\n Button,\n },\n fieldContext,\n formContext,\n});\n"],"names":["useAppForm","createFormHook","TfTextField","TfNumberField","TfMultiSelect","TfSingleSelect","TfCheckbox","Button","fieldContext","formContext"],"mappings":"
|
|
1
|
+
{"version":3,"file":"form-hook.js","sources":["../../lib/utilities/form-hook.tsx"],"sourcesContent":["import { createFormHook } from '@tanstack/react-form';\nimport { Button } from '../components/button';\nimport { TfCheckbox } from '../components/checkbox';\nimport { TfMultiSelect } from '../components/multi-select';\nimport { TfNumberField } from '../components/numberfield';\nimport { TfSingleSelect } from '../components/select';\nimport { TfTextField } from '../components/textfield';\nimport { fieldContext, formContext } from '../utilities/form-context';\n\n/** Don't put this in the same file as form-context.tsx, this causes circular dependencies. */\n/** TODO, lazy loading when fieldComponents are large */\n/**\n * Builder for form logic and user interfaces\n */\n/**\n * A small builder that wires the form library to the concrete UI components used across the app.\n * `createFormHook` returns a `useAppForm` hook which contains standard wiring and default components for\n * fields and form-level controls.\n *\n * It exports only the `useAppForm` hook. Consumers (forms in codebase) call `useAppForm` to access the form API and default components.\n */\nexport const { useAppForm } = createFormHook({\n fieldComponents: {\n TfTextField,\n TfNumberField,\n TfMultiSelect,\n TfSingleSelect,\n TfCheckbox,\n },\n formComponents: {\n Button,\n },\n fieldContext,\n formContext,\n});\n"],"names":["useAppForm","createFormHook","TfTextField","TfNumberField","TfMultiSelect","TfSingleSelect","TfCheckbox","Button","fieldContext","formContext"],"mappings":"qyBAqBO,KAAM,CAAE,WAAAA,CAAA,EAAeC,EAAe,CACzC,gBAAiB,CACb,YAAAC,EACA,cAAAC,EACA,cAAAC,EACA,eAAAC,EACA,WAAAC,CAAA,EAEJ,eAAgB,CACZ,OAAAC,CAAA,EAEJ,aAAAC,EACA,YAAAC,CACJ,CAAC"}
|
package/dist/utilities/form.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { FieldApi, FormApi } from '@tanstack/react-form';
|
|
|
3
3
|
export type AppFormApi<TValues> = FormApi<TValues, any, any, any, any, any, any, any, any, any>;
|
|
4
4
|
/**
|
|
5
5
|
* Utility function to submit a form with a handler that receives the values and the formApi.
|
|
6
|
-
* @param onSubmit - The handler function to call with the values and the formApi.
|
|
6
|
+
* @param onSubmit - The async handler function to call with the values and the formApi.
|
|
7
7
|
* @returns A function that can be used to submit the form. It will filter out disabled fields from the values.
|
|
8
8
|
*/
|
|
9
9
|
export declare function tfOnSubmit<TValues>(onSubmit: ({ values, formApi }: {
|
|
@@ -12,4 +12,9 @@ export declare function tfOnSubmit<TValues>(onSubmit: ({ values, formApi }: {
|
|
|
12
12
|
}) => Promise<any> | any): ({ formApi }: {
|
|
13
13
|
formApi: AppFormApi<TValues>;
|
|
14
14
|
}) => Promise<any>;
|
|
15
|
+
/**
|
|
16
|
+
* Small utility to create a single string from a field's validation errors.
|
|
17
|
+
* Useful for rendering a concise error message in a form UI.
|
|
18
|
+
* @returns a comma-separated string of error messages (or empty string).
|
|
19
|
+
*/
|
|
15
20
|
export declare function getFieldErrorMessage(field: FieldApi<any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any>): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.js","sources":["../../lib/utilities/form.tsx"],"sourcesContent":["import { type AnyFieldMeta, type FieldApi, type FormApi } from '@tanstack/react-form';\n\n/** Utility type to simplify FormApi usage */\nexport type AppFormApi<TValues> = FormApi<TValues, any, any, any, any, any, any, any, any, any>;\n\n/**\n * Utility function to submit a form with a handler that receives the values and the formApi.\n * @param onSubmit - The handler function to call with the values and the formApi.\n * @returns A function that can be used to submit the form. It will filter out disabled fields from the values.\n */\nexport function tfOnSubmit<TValues>(\n onSubmit: ({ values, formApi }: { values: TValues; formApi: AppFormApi<TValues> }) => Promise<any> | any\n) {\n return async ({ formApi }: { formApi: AppFormApi<TValues> }): Promise<any> => {\n const values = pickEnabledFields(formApi.state.values, formApi);\n\n await onSubmit({ values, formApi });\n };\n}\nfunction pickEnabledFields<TValues>(rawValues: TValues, formApi: AppFormApi<TValues>): TValues {\n const result: TValues = {} as TValues;\n\n //TODO: Nested objects are not supported yet\n for (const key in rawValues) {\n const meta = formApi.getFieldMeta(key) as AnyFieldMeta & {\n disabled?: boolean;\n };\n if (!meta?.disabled) {\n result[key] = rawValues[key];\n }\n }\n\n return result;\n}\n\nexport function getFieldErrorMessage(\n field: FieldApi<any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any>\n): string {\n return field?.state.meta.errors.map(e => e?.message).join(',');\n}\n"],"names":["tfOnSubmit","onSubmit","formApi","values","pickEnabledFields","rawValues","result","key","getFieldErrorMessage","field"],"mappings":"AAUO,SAASA,EACZC,EACF,CACE,MAAO,OAAO,CAAE,QAAAC,KAA8D,CAC1E,MAAMC,EAASC,EAAkBF,EAAQ,MAAM,OAAQA,CAAO,EAE9D,MAAMD,EAAS,CAAE,OAAAE,EAAQ,QAAAD,EAAS,CACtC,CACJ,
|
|
1
|
+
{"version":3,"file":"form.js","sources":["../../lib/utilities/form.tsx"],"sourcesContent":["import { type AnyFieldMeta, type FieldApi, type FormApi } from '@tanstack/react-form';\n\n/** Utility type to simplify FormApi usage */\nexport type AppFormApi<TValues> = FormApi<TValues, any, any, any, any, any, any, any, any, any>;\n\n/**\n * Utility function to submit a form with a handler that receives the values and the formApi.\n * @param onSubmit - The async handler function to call with the values and the formApi.\n * @returns A function that can be used to submit the form. It will filter out disabled fields from the values.\n */\nexport function tfOnSubmit<TValues>(\n onSubmit: ({ values, formApi }: { values: TValues; formApi: AppFormApi<TValues> }) => Promise<any> | any\n) {\n return async ({ formApi }: { formApi: AppFormApi<TValues> }): Promise<any> => {\n const values = pickEnabledFields(formApi.state.values, formApi);\n\n await onSubmit({ values, formApi });\n };\n}\n\n/**\n * Internal helper used by `tfOnSubmit`. It filters out any fields that are\n * marked as disabled in the field meta before sending the values to submit\n * handlers.\n */\nfunction pickEnabledFields<TValues>(rawValues: TValues, formApi: AppFormApi<TValues>): TValues {\n const result: TValues = {} as TValues;\n\n //TODO: Nested objects are not supported yet\n for (const key in rawValues) {\n const meta = formApi.getFieldMeta(key) as AnyFieldMeta & {\n disabled?: boolean;\n };\n if (!meta?.disabled) {\n result[key] = rawValues[key];\n }\n }\n\n return result;\n}\n\n/**\n * Small utility to create a single string from a field's validation errors.\n * Useful for rendering a concise error message in a form UI.\n * @returns a comma-separated string of error messages (or empty string).\n */\nexport function getFieldErrorMessage(\n field: FieldApi<any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any>\n): string {\n return field?.state.meta.errors.map(e => e?.message).join(',');\n}\n"],"names":["tfOnSubmit","onSubmit","formApi","values","pickEnabledFields","rawValues","result","key","getFieldErrorMessage","field"],"mappings":"AAUO,SAASA,EACZC,EACF,CACE,MAAO,OAAO,CAAE,QAAAC,KAA8D,CAC1E,MAAMC,EAASC,EAAkBF,EAAQ,MAAM,OAAQA,CAAO,EAE9D,MAAMD,EAAS,CAAE,OAAAE,EAAQ,QAAAD,EAAS,CACtC,CACJ,CAOA,SAASE,EAA2BC,EAAoBH,EAAuC,CAC3F,MAAMI,EAAkB,CAAA,EAGxB,UAAWC,KAAOF,EACDH,EAAQ,aAAaK,CAAG,GAG1B,WACPD,EAAOC,CAAG,EAAIF,EAAUE,CAAG,GAInC,OAAOD,CACX,CAOO,SAASE,EACZC,EACM,CACN,OAAOA,GAAO,MAAM,KAAK,OAAO,OAAS,GAAG,OAAO,EAAE,KAAK,GAAG,CACjE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resources.js","sources":["../../lib/utilities/resources.tsx"],"sourcesContent":["import type { components, operations } from '@cryptlex/web-api-types/develop';\nimport { createContext, use } from 'react';\nimport { toTitleCase } from './string';\n\nexport type ApiSchema<T extends keyof components['schemas']> = components['schemas'][T];\nexport type ApiQuery<T extends keyof operations> = NonNullable<operations[T]['parameters']['query']>;\nexport type ApiFilter<T extends keyof operations> = Omit<ApiQuery<T>, 'page' | 'limit' | 'sort' | 'search'>;\nexport type ApiFilters<T extends keyof operations> = NonNullable<ApiFilter<T>>;\nexport type CtxPortals = 'customer-portal' | 'system-portal' | 'reseller-portal' | 'admin-portal';\n// Display names specific to customer and reseller portal\nconst OTHER_PORTALS_DISPLAY_NAME: Record<string, string> = {\n 'product.displayName': 'Product',\n // TanStack Table converts . -> _ TODO\n product_displayName: 'Product',\n};\n\n/** Resource Name should ALWAYS be in singular form */\nexport const RESOURCE_NAMES = [\n 'access-token',\n 'account',\n 'activation',\n 'activation-log',\n 'admin-role',\n 'audit-log',\n 'automated-email',\n 'automated-email-event-log',\n 'card',\n 'feature-flag',\n 'invoice',\n 'license',\n 'license-template',\n 'maintenance-policy',\n 'organization',\n 'plan',\n 'product',\n 'product-version',\n 'profile',\n 'release',\n 'release-channel',\n 'release-file',\n 'release-platform',\n 'report',\n 'role',\n 'role-claim',\n 'saml-configuration',\n 'segment',\n 'sending-domain',\n 'setting',\n 'tag',\n 'team-member',\n 'trial',\n 'trial-policy',\n 'user',\n 'user-group',\n 'webhook',\n 'webhook-event-log',\n 'webhook-trigger',\n 'reseller',\n 'oidc-configuration',\n 'organization-claim',\n 'reseller-claim',\n] as const;\nexport type ResourceName = (typeof RESOURCE_NAMES)[number];\nexport const RESOURCE_DEFINITIONS: Record<ResourceName, string> = {\n account: 'Your organization account.',\n product: 'Products are the software products you want to license',\n license:\n 'Licenses represent a purchase of your software. These can be linked to customers, and the license key is required to use the product.',\n 'access-token': 'Access Tokens are used to authenticate your API requests.',\n activation: 'Activations, also known as devices/machines/seats are the devices consuming licenses.',\n 'activation-log': 'Activation Log is a log entry of activation/deactivation of a particular license.',\n trial: 'Trial/Trial Activation is a device that has activated a trial of your product.',\n 'audit-log': 'Audit logs contain all the changes made to your account.',\n 'automated-email': 'Automated Email allow you to send marketing emails based on events on the linked product.',\n 'automated-email-event-log':\n 'Automated email event log is the log of all the automated email events for your product.',\n card: 'The payment card for your account.',\n 'feature-flag': 'Feature flags define features that make up tiers for your products.',\n invoice: '',\n 'license-template':\n 'License templates are a blueprint for the licenses you create for your customers and prevent repetition when creating licenses.',\n 'maintenance-policy': 'Maintenance policies represent support contracts and can be linked to licenses.',\n plan: '',\n 'product-version': 'Product Versions are sets of Feature Flags that define the tiers of your products.',\n 'release-channel': 'Release channel is the release channel for your product.',\n 'release-file': 'Release files are files within your created releases.',\n 'release-platform':\n 'Release Platforms differentiate the target platform for your release. Common platforms include \"Windows\", \"macOS\", and \"Linux\".',\n release: 'Releases help you to manage different versions of your app, and secure distribute it to licensed users.',\n report: 'Analytics data for your account',\n 'role-claim': '',\n role: 'Roles define permissions for your team.',\n 'saml-configuration': '',\n segment: 'Sets of filters that can be saved to filter resources.',\n 'trial-policy': 'Trial policies are templates for creating trials for your products.',\n 'webhook-event-log': 'Webhook Event Logs are logs of events that have occured on webhooks.',\n 'webhook-trigger': '',\n webhook: 'Webhooks are HTTP callbacks which are triggered by specific events.',\n organization: '',\n profile: '',\n setting: '',\n tag: 'Tags allow you to manage your licenses and customers on the dashboard.',\n 'team-member': 'Team members can access the account based on their roles.',\n user: 'A user refers to your customer whom you want to license your product.',\n 'sending-domain': 'Allows Cryptlex to send emails on your behalf using your From Email address',\n 'admin-role': 'Roles that have type admin',\n 'user-group': 'Groups of users that you can assign licenses to.',\n reseller: 'Resellers allow you to delegate user management to third parties or partners',\n 'oidc-configuration': '',\n 'organization-claim': '',\n 'reseller-claim': '',\n};\n\nconst RESOURCE_DISPLAY_NAMES: Record<string, string> = {\n id: 'ID',\n createdAt: 'Creation Date',\n scopes: 'Permissions',\n updatedAt: 'Last Updated',\n expiresAt: 'Expiration Date',\n lastSeenAt: 'Last Seen',\n os: 'OS',\n osVersion: 'OS Version',\n key: 'License Key',\n vmName: 'VM Name',\n container: 'Container',\n allowedIpRange: 'Allowed IP Range',\n allowedIpRanges: 'Allowed IP Ranges',\n allowedIpAddresses: 'Allowed IP Addresses',\n disallowedIpAddresses: 'Disallowed IP Addresses',\n allowVmActivation: 'Allow VM Activation',\n disableGeoLocation: 'Disable Geolocation',\n 'user.id': 'User ID',\n userId: 'User',\n productId: 'Product',\n downloads: 'Total Downloads',\n claims: 'Permissions',\n googleSsoEnabled: 'Google Login Enabled',\n lastAttemptedAt: 'Last Attempt Date',\n url: 'URL',\n 'trialPolicy.name': 'Trial Policy Name',\n 'licensePolicy.name': 'License Template Name',\n licensePolicy: 'License Template',\n eventLog: 'Audit Log',\n cc: 'CC Recepients',\n bcc: 'BCC Recepients',\n ipAddress: 'IP Address',\n resellerId: 'Reseller',\n productVersionId: 'Product Version',\n releaseId: 'Release',\n maintenancePolicyId: 'Maintenance Policy',\n webhookId: 'Webhook',\n automatedEmailId: 'Automated Email',\n 'location.countryName': 'Country',\n 'location.ipAddress': 'IP Address',\n 'location.countryCode': 'Country',\n organizationId: 'Organization',\n 'address.country': 'Country',\n 'address.addressLine1': 'Address Line 1',\n 'address.addressLine2': 'Address Line 2',\n responseStatusCode: 'HTTP Status Code',\n resourceId: 'Resource ID',\n Sso: 'SAML SSO 2.0',\n 'reseller.name': 'Reseller',\n sendingDomain: 'Email Sending Domain',\n};\n\nfunction getResourceDisplayName(resourceName: string, portal: CtxPortals) {\n if (portal !== 'admin-portal' && resourceName in OTHER_PORTALS_DISPLAY_NAME) {\n return OTHER_PORTALS_DISPLAY_NAME[resourceName];\n } else if (resourceName in RESOURCE_DISPLAY_NAMES) {\n return RESOURCE_DISPLAY_NAMES[resourceName];\n } else {\n return toTitleCase(resourceName);\n }\n}\n\nconst ProjectContext = createContext<CtxPortals>('admin-portal');\n\nexport function ProjectProvider({ projectName, children }: { projectName: CtxPortals; children: React.ReactNode }) {\n return <ProjectContext.Provider value={projectName}>{children}</ProjectContext.Provider>;\n}\n\nexport function useProjectName(): CtxPortals {\n const projectName = use(ProjectContext);\n return projectName;\n}\n\n// TODO, create story with complete map of resource -> formatter output\nexport function useResourceFormatter(): (resourceName: string) => string {\n const portal = useProjectName();\n return (resourceName: string) => getResourceDisplayName(resourceName, portal);\n}\n\nexport const CTX_RESOURCES = [\n 'account',\n 'activation',\n 'automatedEmail',\n 'billingAddress',\n 'entitlementSet',\n 'feature',\n 'featureEntitlement',\n 'featureFlag',\n 'license',\n 'licenseTemplate',\n 'maintenancePolicy',\n 'oidcConfiguration',\n 'oidcRoleMapping',\n 'organization',\n 'paymentMethod',\n 'personalAccessToken',\n 'plan',\n 'product',\n 'productVersion',\n 'release',\n 'releaseChannel',\n 'releaseFile',\n 'releasePlatform',\n 'reseller',\n 'role',\n 'samlConfiguration',\n 'segment',\n 'sendingDomain',\n 'tag',\n 'trialActivation',\n 'trialPolicy',\n 'user',\n 'userGroup',\n 'webhook',\n] as const;\n\nexport type CtxResourceName = (typeof CTX_RESOURCES)[number];\n\n/**\n * Format multiple license parameters (expired, suspended, revoked) into a single status\n */\nexport function getLicenseStatus(license: any): string {\n const licenseExpired = license.expiresAt && new Date(license.expiresAt) < new Date();\n // Status Column\n switch (true) {\n case license.revoked && license.suspended && licenseExpired:\n return 'Revoked, Suspended, Expired';\n case license.revoked && license.suspended:\n return 'Revoked, Suspended';\n case license.revoked && licenseExpired:\n return 'Revoked, Expired';\n case license.suspended && licenseExpired:\n return 'Suspended, Expired';\n case license.suspended:\n return 'Suspended';\n case license.revoked:\n return 'Revoked';\n case licenseExpired:\n return 'Expired';\n default:\n return 'Active';\n }\n}\ntype OsType = ApiSchema<'ActivationCreateRequestModel'>['os'];\nexport const ALL_OS: Record<OsType, string> = {\n windows: 'Windows',\n macos: 'macOS',\n linux: 'Linux',\n ios: 'iOS',\n android: 'Android',\n};\n"],"names":["OTHER_PORTALS_DISPLAY_NAME","RESOURCE_NAMES","RESOURCE_DEFINITIONS","RESOURCE_DISPLAY_NAMES","getResourceDisplayName","resourceName","portal","toTitleCase","ProjectContext","createContext","ProjectProvider","projectName","children","useProjectName","use","useResourceFormatter","CTX_RESOURCES","getLicenseStatus","license","licenseExpired","ALL_OS"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"resources.js","sources":["../../lib/utilities/resources.tsx"],"sourcesContent":["import type { components, operations } from '@cryptlex/web-api-types/develop';\nimport { createContext, use } from 'react';\nimport { toTitleCase } from './string';\n\nexport type ApiSchema<T extends keyof components['schemas']> = components['schemas'][T];\nexport type ApiQuery<T extends keyof operations> = NonNullable<operations[T]['parameters']['query']>;\nexport type ApiFilter<T extends keyof operations> = Omit<ApiQuery<T>, 'page' | 'limit' | 'sort' | 'search'>;\nexport type ApiFilters<T extends keyof operations> = NonNullable<ApiFilter<T>>;\nexport type CtxPortals = 'customer-portal' | 'system-portal' | 'reseller-portal' | 'admin-portal';\n// Display names specific to customer and reseller portal\nconst OTHER_PORTALS_DISPLAY_NAME: Record<string, string> = {\n 'product.displayName': 'Product',\n // TanStack Table converts . -> _ TODO\n product_displayName: 'Product',\n};\n\n/** Resource Name should ALWAYS be in singular form */\nexport const RESOURCE_NAMES = [\n 'access-token',\n 'account',\n 'activation',\n 'activation-log',\n 'admin-role',\n 'audit-log',\n 'automated-email',\n 'automated-email-event-log',\n 'card',\n 'feature-flag',\n 'invoice',\n 'license',\n 'license-template',\n 'maintenance-policy',\n 'organization',\n 'plan',\n 'product',\n 'product-version',\n 'profile',\n 'release',\n 'release-channel',\n 'release-file',\n 'release-platform',\n 'report',\n 'role',\n 'role-claim',\n 'saml-configuration',\n 'segment',\n 'sending-domain',\n 'setting',\n 'tag',\n 'team-member',\n 'trial',\n 'trial-policy',\n 'user',\n 'user-group',\n 'webhook',\n 'webhook-event-log',\n 'webhook-trigger',\n 'reseller',\n 'oidc-configuration',\n 'organization-claim',\n 'reseller-claim',\n] as const;\nexport type ResourceName = (typeof RESOURCE_NAMES)[number];\nexport const RESOURCE_DEFINITIONS: Record<ResourceName, string> = {\n account: 'Your organization account.',\n product: 'Products are the software products you want to license',\n license:\n 'Licenses represent a purchase of your software. These can be linked to customers, and the license key is required to use the product.',\n 'access-token': 'Access Tokens are used to authenticate your API requests.',\n activation: 'Activations, also known as devices/machines/seats are the devices consuming licenses.',\n 'activation-log': 'Activation Log is a log entry of activation/deactivation of a particular license.',\n trial: 'Trial/Trial Activation is a device that has activated a trial of your product.',\n 'audit-log': 'Audit logs contain all the changes made to your account.',\n 'automated-email': 'Automated Email allow you to send marketing emails based on events on the linked product.',\n 'automated-email-event-log':\n 'Automated email event log is the log of all the automated email events for your product.',\n card: 'The payment card for your account.',\n 'feature-flag': 'Feature flags define features that make up tiers for your products.',\n invoice: '',\n 'license-template':\n 'License templates are a blueprint for the licenses you create for your customers and prevent repetition when creating licenses.',\n 'maintenance-policy': 'Maintenance policies represent support contracts and can be linked to licenses.',\n plan: '',\n 'product-version': 'Product Versions are sets of Feature Flags that define the tiers of your products.',\n 'release-channel': 'Release channel is the release channel for your product.',\n 'release-file': 'Release files are files within your created releases.',\n 'release-platform':\n 'Release Platforms differentiate the target platform for your release. Common platforms include \"Windows\", \"macOS\", and \"Linux\".',\n release: 'Releases help you to manage different versions of your app, and secure distribute it to licensed users.',\n report: 'Analytics data for your account',\n 'role-claim': '',\n role: 'Roles define permissions for your team.',\n 'saml-configuration': '',\n segment: 'Sets of filters that can be saved to filter resources.',\n 'trial-policy': 'Trial policies are templates for creating trials for your products.',\n 'webhook-event-log': 'Webhook Event Logs are logs of events that have occured on webhooks.',\n 'webhook-trigger': '',\n webhook: 'Webhooks are HTTP callbacks which are triggered by specific events.',\n organization: '',\n profile: '',\n setting: '',\n tag: 'Tags allow you to manage your licenses and customers on the dashboard.',\n 'team-member': 'Team members can access the account based on their roles.',\n user: 'A user refers to your customer whom you want to license your product.',\n 'sending-domain': 'Allows Cryptlex to send emails on your behalf using your From Email address',\n 'admin-role': 'Roles that have type admin',\n 'user-group': 'Groups of users that you can assign licenses to.',\n reseller: 'Resellers allow you to delegate user management to third parties or partners',\n 'oidc-configuration': '',\n 'organization-claim': '',\n 'reseller-claim': '',\n};\n\nconst RESOURCE_DISPLAY_NAMES: Record<string, string> = {\n id: 'ID',\n createdAt: 'Creation Date',\n scopes: 'Permissions',\n updatedAt: 'Last Updated',\n expiresAt: 'Expiration Date',\n lastSeenAt: 'Last Seen',\n os: 'OS',\n osVersion: 'OS Version',\n key: 'License Key',\n vmName: 'VM Name',\n container: 'Container',\n allowedIpRange: 'Allowed IP Range',\n allowedIpRanges: 'Allowed IP Ranges',\n allowedIpAddresses: 'Allowed IP Addresses',\n disallowedIpAddresses: 'Disallowed IP Addresses',\n allowVmActivation: 'Allow VM Activation',\n disableGeoLocation: 'Disable Geolocation',\n 'user.id': 'User ID',\n userId: 'User',\n productId: 'Product',\n downloads: 'Total Downloads',\n claims: 'Permissions',\n googleSsoEnabled: 'Google Login Enabled',\n lastAttemptedAt: 'Last Attempt Date',\n url: 'URL',\n 'trialPolicy.name': 'Trial Policy Name',\n 'licensePolicy.name': 'License Template Name',\n licensePolicy: 'License Template',\n eventLog: 'Audit Log',\n cc: 'CC Recepients',\n bcc: 'BCC Recepients',\n ipAddress: 'IP Address',\n resellerId: 'Reseller',\n productVersionId: 'Product Version',\n releaseId: 'Release',\n maintenancePolicyId: 'Maintenance Policy',\n webhookId: 'Webhook',\n automatedEmailId: 'Automated Email',\n 'location.countryName': 'Country',\n 'location.ipAddress': 'IP Address',\n 'location.countryCode': 'Country',\n organizationId: 'Organization',\n 'address.country': 'Country',\n 'address.addressLine1': 'Address Line 1',\n 'address.addressLine2': 'Address Line 2',\n responseStatusCode: 'HTTP Status Code',\n resourceId: 'Resource ID',\n Sso: 'SAML SSO 2.0',\n 'reseller.name': 'Reseller',\n sendingDomain: 'Email Sending Domain',\n};\n\nfunction getResourceDisplayName(resourceName: string, portal: CtxPortals) {\n if (portal !== 'admin-portal' && resourceName in OTHER_PORTALS_DISPLAY_NAME) {\n return OTHER_PORTALS_DISPLAY_NAME[resourceName];\n } else if (resourceName in RESOURCE_DISPLAY_NAMES) {\n return RESOURCE_DISPLAY_NAMES[resourceName];\n } else {\n return toTitleCase(resourceName);\n }\n}\n\nconst ProjectContext = createContext<CtxPortals>('admin-portal');\n\nexport function ProjectProvider({ projectName, children }: { projectName: CtxPortals; children: React.ReactNode }) {\n return <ProjectContext.Provider value={projectName}>{children}</ProjectContext.Provider>;\n}\n\nexport function useProjectName(): CtxPortals {\n const projectName = use(ProjectContext);\n return projectName;\n}\n\nexport function useResourceFormatter(): (resourceName: string) => string {\n const portal = useProjectName();\n return (resourceName: string) => getResourceDisplayName(resourceName, portal);\n}\n\nexport const CTX_RESOURCES = [\n 'account',\n 'activation',\n 'automatedEmail',\n 'billingAddress',\n 'entitlementSet',\n 'feature',\n 'featureEntitlement',\n 'featureFlag',\n 'license',\n 'licenseTemplate',\n 'maintenancePolicy',\n 'oidcConfiguration',\n 'oidcRoleMapping',\n 'organization',\n 'paymentMethod',\n 'personalAccessToken',\n 'plan',\n 'product',\n 'productVersion',\n 'release',\n 'releaseChannel',\n 'releaseFile',\n 'releasePlatform',\n 'reseller',\n 'role',\n 'samlConfiguration',\n 'segment',\n 'sendingDomain',\n 'tag',\n 'trialActivation',\n 'trialPolicy',\n 'user',\n 'userGroup',\n 'webhook',\n] as const;\n\nexport type CtxResourceName = (typeof CTX_RESOURCES)[number];\n\n/**\n * Format multiple license parameters (expired, suspended, revoked) into a single status\n */\nexport function getLicenseStatus(license: any): string {\n const licenseExpired = license.expiresAt && new Date(license.expiresAt) < new Date();\n // Status Column\n switch (true) {\n case license.revoked && license.suspended && licenseExpired:\n return 'Revoked, Suspended, Expired';\n case license.revoked && license.suspended:\n return 'Revoked, Suspended';\n case license.revoked && licenseExpired:\n return 'Revoked, Expired';\n case license.suspended && licenseExpired:\n return 'Suspended, Expired';\n case license.suspended:\n return 'Suspended';\n case license.revoked:\n return 'Revoked';\n case licenseExpired:\n return 'Expired';\n default:\n return 'Active';\n }\n}\ntype OsType = ApiSchema<'ActivationCreateRequestModel'>['os'];\nexport const ALL_OS: Record<OsType, string> = {\n windows: 'Windows',\n macos: 'macOS',\n linux: 'Linux',\n ios: 'iOS',\n android: 'Android',\n};\n"],"names":["OTHER_PORTALS_DISPLAY_NAME","RESOURCE_NAMES","RESOURCE_DEFINITIONS","RESOURCE_DISPLAY_NAMES","getResourceDisplayName","resourceName","portal","toTitleCase","ProjectContext","createContext","ProjectProvider","projectName","children","useProjectName","use","useResourceFormatter","CTX_RESOURCES","getLicenseStatus","license","licenseExpired","ALL_OS"],"mappings":"mJAUA,MAAMA,EAAqD,CACvD,sBAAuB,UAEvB,oBAAqB,SACzB,EAGaC,EAAiB,CAC1B,eACA,UACA,aACA,iBACA,aACA,YACA,kBACA,4BACA,OACA,eACA,UACA,UACA,mBACA,qBACA,eACA,OACA,UACA,kBACA,UACA,UACA,kBACA,eACA,mBACA,SACA,OACA,aACA,qBACA,UACA,iBACA,UACA,MACA,cACA,QACA,eACA,OACA,aACA,UACA,oBACA,kBACA,WACA,qBACA,qBACA,gBACJ,EAEaC,EAAqD,CAC9D,QAAS,6BACT,QAAS,yDACT,QACI,wIACJ,eAAgB,4DAChB,WAAY,wFACZ,iBAAkB,oFAClB,MAAO,iFACP,YAAa,2DACb,kBAAmB,4FACnB,4BACI,2FACJ,KAAM,qCACN,eAAgB,sEAChB,QAAS,GACT,mBACI,kIACJ,qBAAsB,kFACtB,KAAM,GACN,kBAAmB,qFACnB,kBAAmB,2DACnB,eAAgB,wDAChB,mBACI,kIACJ,QAAS,0GACT,OAAQ,kCACR,aAAc,GACd,KAAM,0CACN,qBAAsB,GACtB,QAAS,yDACT,eAAgB,sEAChB,oBAAqB,uEACrB,kBAAmB,GACnB,QAAS,sEACT,aAAc,GACd,QAAS,GACT,QAAS,GACT,IAAK,yEACL,cAAe,4DACf,KAAM,wEACN,iBAAkB,8EAClB,aAAc,6BACd,aAAc,mDACd,SAAU,+EACV,qBAAsB,GACtB,qBAAsB,GACtB,iBAAkB,EACtB,EAEMC,EAAiD,CACnD,GAAI,KACJ,UAAW,gBACX,OAAQ,cACR,UAAW,eACX,UAAW,kBACX,WAAY,YACZ,GAAI,KACJ,UAAW,aACX,IAAK,cACL,OAAQ,UACR,UAAW,YACX,eAAgB,mBAChB,gBAAiB,oBACjB,mBAAoB,uBACpB,sBAAuB,0BACvB,kBAAmB,sBACnB,mBAAoB,sBACpB,UAAW,UACX,OAAQ,OACR,UAAW,UACX,UAAW,kBACX,OAAQ,cACR,iBAAkB,uBAClB,gBAAiB,oBACjB,IAAK,MACL,mBAAoB,oBACpB,qBAAsB,wBACtB,cAAe,mBACf,SAAU,YACV,GAAI,gBACJ,IAAK,iBACL,UAAW,aACX,WAAY,WACZ,iBAAkB,kBAClB,UAAW,UACX,oBAAqB,qBACrB,UAAW,UACX,iBAAkB,kBAClB,uBAAwB,UACxB,qBAAsB,aACtB,uBAAwB,UACxB,eAAgB,eAChB,kBAAmB,UACnB,uBAAwB,iBACxB,uBAAwB,iBACxB,mBAAoB,mBACpB,WAAY,cACZ,IAAK,eACL,gBAAiB,WACjB,cAAe,sBACnB,EAEA,SAASC,EAAuBC,EAAsBC,EAAoB,CACtE,OAAIA,IAAW,gBAAkBD,KAAgBL,EACtCA,EAA2BK,CAAY,EACvCA,KAAgBF,EAChBA,EAAuBE,CAAY,EAEnCE,EAAYF,CAAY,CAEvC,CAEA,MAAMG,EAAiBC,EAA0B,cAAc,EAExD,SAASC,EAAgB,CAAE,YAAAC,EAAa,SAAAC,GAAoE,CAC/G,SAAQJ,EAAe,SAAf,CAAwB,MAAOG,EAAc,SAAAC,EAAS,CAClE,CAEO,SAASC,GAA6B,CAEzC,OADoBC,EAAIN,CAAc,CAE1C,CAEO,SAASO,GAAyD,CACrE,MAAMT,EAASO,EAAA,EACf,OAAQR,GAAyBD,EAAuBC,EAAcC,CAAM,CAChF,CAEO,MAAMU,EAAgB,CACzB,UACA,aACA,iBACA,iBACA,iBACA,UACA,qBACA,cACA,UACA,kBACA,oBACA,oBACA,kBACA,eACA,gBACA,sBACA,OACA,UACA,iBACA,UACA,iBACA,cACA,kBACA,WACA,OACA,oBACA,UACA,gBACA,MACA,kBACA,cACA,OACA,YACA,SACJ,EAOO,SAASC,EAAiBC,EAAsB,CACnD,MAAMC,EAAiBD,EAAQ,WAAa,IAAI,KAAKA,EAAQ,SAAS,EAAI,IAAI,KAE9E,OAAQ,GAAA,CACJ,KAAKA,EAAQ,SAAWA,EAAQ,WAAaC,GACzC,MAAO,8BACX,KAAKD,EAAQ,SAAWA,EAAQ,WAC5B,MAAO,qBACX,KAAKA,EAAQ,SAAWC,GACpB,MAAO,mBACX,KAAKD,EAAQ,WAAaC,GACtB,MAAO,qBACX,KAAKD,EAAQ,UACT,MAAO,YACX,KAAKA,EAAQ,QACT,MAAO,UACX,KAAKC,EACD,MAAO,UACX,QACI,MAAO,QAAA,CAEnB,CAEO,MAAMC,EAAiC,CAC1C,QAAS,UACT,MAAO,QACP,MAAO,QACP,IAAK,MACL,QAAS,SACb"}
|
package/lib/index.css
CHANGED
|
@@ -224,16 +224,4 @@
|
|
|
224
224
|
.tw-prose a {
|
|
225
225
|
@apply link;
|
|
226
226
|
}
|
|
227
|
-
|
|
228
|
-
*::-webkit-scrollbar {
|
|
229
|
-
@apply size-2;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
*::-webkit-scrollbar-track {
|
|
233
|
-
@apply bg-card rounded-none;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
*::-webkit-scrollbar-thumb {
|
|
237
|
-
@apply bg-foreground/70 hover:bg-foreground;
|
|
238
|
-
}
|
|
239
227
|
}
|