@bsuite/ui 1.2.0 → 1.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"BrandingCard.d.ts","sourceRoot":"","sources":["../../src/branding/BrandingCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAGhD,MAAM,WAAW,iBAAiB;IAChC,qCAAqC;IACrC,QAAQ,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAC3B,CAAA;IACD,mDAAmD;IACnD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9D,qDAAqD;IACrD,iBAAiB,EAAE,CAAC,KAAK,EAAE;QACzB,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;QACjC,QAAQ,CAAC,EAAE,OAAO,CAAA;KACnB,KAAK,SAAS,CAAA;IACf,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AASD,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,QAAQ,EACR,iBAAiB,EACjB,SAAS,EACT,QAAgB,EAChB,KAAwB,EACxB,WAAW,GACZ,EAAE,iBAAiB,+BA8QnB"}
1
+ {"version":3,"file":"BrandingCard.d.ts","sourceRoot":"","sources":["../../src/branding/BrandingCard.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAGhD,MAAM,WAAW,iBAAiB;IAChC,qCAAqC;IACrC,QAAQ,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAC3B,CAAA;IACD,mDAAmD;IACnD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9D,qDAAqD;IACrD,iBAAiB,EAAE,CAAC,KAAK,EAAE;QACzB,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;QACjC,QAAQ,CAAC,EAAE,OAAO,CAAA;KACnB,KAAK,SAAS,CAAA;IACf,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AASD,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,QAAQ,EACR,iBAAiB,EACjB,SAAS,EACT,QAAgB,EAChB,KAAwB,EACxB,WAAW,GACZ,EAAE,iBAAiB,+BA8QnB"}
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
3
  /**
3
4
  * BrandingCard — A card component for displaying and editing branding settings
@@ -1 +1 @@
1
- {"version":3,"file":"ColorEditorSheet.d.ts","sourceRoot":"","sources":["../../src/branding/ColorEditorSheet.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAG3D,MAAM,WAAW,qBAAqB;IACpC,gCAAgC;IAChC,IAAI,EAAE,OAAO,CAAA;IACb,uCAAuC;IACvC,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,oCAAoC;IACpC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,qDAAqD;IACrD,YAAY,EAAE,CAAC,KAAK,EAAE;QACpB,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;QACjC,QAAQ,CAAC,EAAE,OAAO,CAAA;KACnB,KAAK,SAAS,CAAA;IACf,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,YAAY,EACZ,KAAoB,EACpB,WAAW,EACX,KAAK,EACL,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,QAAgB,GACjB,EAAE,qBAAqB,sCAuIvB"}
1
+ {"version":3,"file":"ColorEditorSheet.d.ts","sourceRoot":"","sources":["../../src/branding/ColorEditorSheet.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAG3D,MAAM,WAAW,qBAAqB;IACpC,gCAAgC;IAChC,IAAI,EAAE,OAAO,CAAA;IACb,uCAAuC;IACvC,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,oCAAoC;IACpC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,qDAAqD;IACrD,YAAY,EAAE,CAAC,KAAK,EAAE;QACpB,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;QACjC,QAAQ,CAAC,EAAE,OAAO,CAAA;KACnB,KAAK,SAAS,CAAA;IACf,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,YAAY,EACZ,KAAoB,EACpB,WAAW,EACX,KAAK,EACL,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,QAAgB,GACjB,EAAE,qBAAqB,sCAuIvB"}
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  /**
3
4
  * ColorEditorSheet — A sheet/dialog for editing branding colors
@@ -1 +1 @@
1
- {"version":3,"file":"OklchColorPicker.d.ts","sourceRoot":"","sources":["../../src/branding/OklchColorPicker.tsx"],"names":[],"mappings":"AAyBA,MAAM,WAAW,qBAAqB;IACpC,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kCAAkC;IAClC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AA+BD,wBAAgB,gBAAgB,CAAC,EAC/B,KAAkC,EAClC,QAAQ,EACR,KAAK,EACL,QAAgB,EAChB,SAAS,EACT,WAAW,EACX,KAAK,GACN,EAAE,qBAAqB,+BA8LvB"}
1
+ {"version":3,"file":"OklchColorPicker.d.ts","sourceRoot":"","sources":["../../src/branding/OklchColorPicker.tsx"],"names":[],"mappings":"AA2BA,MAAM,WAAW,qBAAqB;IACpC,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kCAAkC;IAClC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AA+BD,wBAAgB,gBAAgB,CAAC,EAC/B,KAAkC,EAClC,QAAQ,EACR,KAAK,EACL,QAAgB,EAChB,SAAS,EACT,WAAW,EACX,KAAK,GACN,EAAE,qBAAqB,+BA8LvB"}
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  /**
3
4
  * OklchColorPicker — A color input component for OKLCH color format
@@ -1 +1 @@
1
- {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAGzD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,QAAA,MAAM,OAAO;;;;;;;;;;;;;;;;sFAYX,CAAA;AAGF,UAAU,kBAAmB,SAAQ,WAAW;IAG9C,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,QAAA,MAAM,aAAa,GAAI,4CAKpB,kBAAkB,sBAYpB,CAAA;AAED,QAAA,MAAM,YAAY;;;;;;;0FAehB,CAAA;AAIF,QAAA,MAAM,WAAW;;;;;;;;sFASf,CAAA;AAIF,QAAA,MAAM,YAAY;;;;;;uJAKhB,CAAA;AAIF,QAAA,MAAM,YAAY;;;;;;;;;;sFAYhB,CAAA;AAIF,QAAA,MAAM,gBAAgB;;;;;;sFASpB,CAAA;AAGF,QAAA,MAAM,WAAW;;;;;;;;;;;;sFAYf,CAAA;AAIF,QAAA,MAAM,eAAe;8BAA6B,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;;CAOtF,CAAA;AAGD,OAAO,EACL,OAAO,EACP,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,eAAe,GAChB,CAAA"}
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAGzD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,QAAA,MAAM,OAAO;;;;;;;;;;;;;;;;sFAYX,CAAA;AAGF,UAAU,kBAAmB,SAAQ,WAAW;IAG9C,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,QAAA,MAAM,aAAa,GAAI,4CAKpB,kBAAkB,sBAYpB,CAAA;AAED,QAAA,MAAM,YAAY;;;;;;;0FAehB,CAAA;AAIF,QAAA,MAAM,WAAW;;;;;;;;sFASf,CAAA;AAIF,QAAA,MAAM,YAAY;;;;;;uJAKhB,CAAA;AAIF,QAAA,MAAM,YAAY;;;;;;;;;;sFAYhB,CAAA;AAIF,QAAA,MAAM,gBAAgB;;;;;;sFASpB,CAAA;AAGF,QAAA,MAAM,WAAW;;;;;;;;;;;;sFAYf,CAAA;AAIF,QAAA,MAAM,eAAe;8BAA6B,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;;CAOtF,CAAA;AAGD,OAAO,EACL,OAAO,EACP,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,eAAe,GAChB,CAAA"}
package/dist/command.js CHANGED
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { Command as CommandPrimitive } from 'cmdk';
3
4
  import { Search } from 'lucide-react';
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../src/dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,wBAAwB,EAAqB,KAAK,cAAc,EAAE,MAAM,OAAO,CAAA;AACzG,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAA;AAGzD,eAAO,MAAM,MAAM,iDAAuB,CAAA;AAC1C,eAAO,MAAM,aAAa,kIAA0B,CAAA;AACpD,eAAO,MAAM,WAAW,gIAAwB,CAAA;AAChD,eAAO,MAAM,YAAY,uDAAyB,CAAA;AAElD,MAAM,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,CAAA;AACzF,MAAM,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,CAAA;AAEzF,eAAO,MAAM,aAAa,4LAexB,CAAA;AAEF,eAAO,MAAM,aAAa,4LA8BxB,CAAA;AAEF,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,cAAc,CAAC,+BAEnF;AAED,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,cAAc,CAAC,+BAOnF;AAED,eAAO,MAAM,WAAW,kMAWtB,CAAA;AAEF,eAAO,MAAM,iBAAiB,4MAW5B,CAAA"}
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../src/dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,wBAAwB,EAAqB,KAAK,cAAc,EAAE,MAAM,OAAO,CAAA;AACzG,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAA;AAGzD,eAAO,MAAM,MAAM,iDAAuB,CAAA;AAC1C,eAAO,MAAM,aAAa,kIAA0B,CAAA;AACpD,eAAO,MAAM,WAAW,gIAAwB,CAAA;AAChD,eAAO,MAAM,YAAY,uDAAyB,CAAA;AAElD,MAAM,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,CAAA;AACzF,MAAM,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,CAAA;AAEzF,eAAO,MAAM,aAAa,4LAexB,CAAA;AAEF,eAAO,MAAM,aAAa,4LA8BxB,CAAA;AAEF,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,cAAc,CAAC,+BAEnF;AAED,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,cAAc,CAAC,+BAOnF;AAED,eAAO,MAAM,WAAW,kMAWtB,CAAA;AAEF,eAAO,MAAM,iBAAiB,4MAW5B,CAAA"}
package/dist/dialog.js CHANGED
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { forwardRef } from 'react';
3
4
  import * as DialogPrimitive from '@radix-ui/react-dialog';
@@ -166,6 +166,23 @@ export interface EntitySelectorProps<T extends Record<string, unknown>> {
166
166
  debounceMs?: number;
167
167
  /** Max results to fetch */
168
168
  limit?: number;
169
+ /**
170
+ * Column used to ORDER the search results before `limit` truncates them.
171
+ *
172
+ * A `.limit()` with no `.order()` returns an ARBITRARY subset of the matches —
173
+ * Postgres hands back whatever the scan reaches first. Once a table holds more
174
+ * rows matching a search term than `limit`, the row the user is looking for
175
+ * (typically the one they just created) silently falls outside the window and
176
+ * the picker claims it does not exist. Measured in crm7: 366 clients matched
177
+ * `%Acme%` against a limit of 50.
178
+ *
179
+ * Defaults to `created_at` descending so the newest match is always offered.
180
+ * A table WITHOUT that column must pass its own — but an unknown column fails
181
+ * SOFT (see fetchItems), because `table` is dynamic at some call sites.
182
+ */
183
+ orderBy?: string;
184
+ /** Sort direction for {@link orderBy}. Defaults to descending (newest first). */
185
+ orderAscending?: boolean;
169
186
  /** Allow clearing the selection */
170
187
  clearable?: boolean;
171
188
  /** Additional className for the trigger button */
@@ -247,6 +264,6 @@ export interface EntitySelectorProps<T extends Record<string, unknown>> {
247
264
  */
248
265
  suggestedLabel?: string;
249
266
  }
250
- export declare function EntitySelector<T extends Record<string, unknown>>({ supabaseClient, logger, table, schema, value, onSelect, displayField, secondaryField, searchColumns, selectColumns, filterFn, placeholder, disabled, onQuickAdd, quickAddLabel, minChars, debounceMs, limit, clearable, className, selectedLabel, onQueryStateChange, renderRow, id, name, 'aria-describedby': ariaDescribedBy, 'aria-invalid': ariaInvalid, 'aria-labelledby': ariaLabelledBy, resolveValueTable, resolveValueSchema, resolveValueSelectColumns, suggestedIds, suggestedLabel, }: EntitySelectorProps<T>): import("react").JSX.Element;
267
+ export declare function EntitySelector<T extends Record<string, unknown>>({ supabaseClient, logger, table, schema, value, onSelect, displayField, secondaryField, searchColumns, selectColumns, filterFn, placeholder, disabled, onQuickAdd, quickAddLabel, minChars, debounceMs, limit, orderBy, orderAscending, clearable, className, selectedLabel, onQueryStateChange, renderRow, id, name, 'aria-describedby': ariaDescribedBy, 'aria-invalid': ariaInvalid, 'aria-labelledby': ariaLabelledBy, resolveValueTable, resolveValueSchema, resolveValueSelectColumns, suggestedIds, suggestedLabel, }: EntitySelectorProps<T>): import("react").JSX.Element;
251
268
  export default EntitySelector;
252
269
  //# sourceMappingURL=entity-selector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"entity-selector.d.ts","sourceRoot":"","sources":["../src/entity-selector.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"entity-selector.d.ts","sourceRoot":"","sources":["../src/entity-selector.tsx"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
3
  import { Check, ChevronsUpDown, Loader2, Plus, X } from 'lucide-react';
3
4
  import { useCallback, useEffect, useRef, useState } from 'react';
@@ -9,7 +10,7 @@ import { cn } from './utils.js';
9
10
  // ============================================================================
10
11
  // COMPONENT
11
12
  // ============================================================================
12
- export function EntitySelector({ supabaseClient, logger = console, table, schema, value, onSelect, displayField, secondaryField, searchColumns, selectColumns = '*', filterFn, placeholder = 'Search...', disabled = false, onQuickAdd, quickAddLabel = 'Create new', minChars = 0, debounceMs = 250, limit = 50, clearable = true, className, selectedLabel, onQueryStateChange, renderRow, id, name, 'aria-describedby': ariaDescribedBy, 'aria-invalid': ariaInvalid, 'aria-labelledby': ariaLabelledBy, resolveValueTable, resolveValueSchema, resolveValueSelectColumns, suggestedIds, suggestedLabel = 'Already linked', }) {
13
+ export function EntitySelector({ supabaseClient, logger = console, table, schema, value, onSelect, displayField, secondaryField, searchColumns, selectColumns = '*', filterFn, placeholder = 'Search...', disabled = false, onQuickAdd, quickAddLabel = 'Create new', minChars = 0, debounceMs = 250, limit = 50, orderBy = 'created_at', orderAscending = false, clearable = true, className, selectedLabel, onQueryStateChange, renderRow, id, name, 'aria-describedby': ariaDescribedBy, 'aria-invalid': ariaInvalid, 'aria-labelledby': ariaLabelledBy, resolveValueTable, resolveValueSchema, resolveValueSelectColumns, suggestedIds, suggestedLabel = 'Already linked', }) {
13
14
  const [open, setOpen] = useState(false);
14
15
  const [query, setQuery] = useState('');
15
16
  const [items, setItems] = useState([]);
@@ -106,25 +107,57 @@ export function EntitySelector({ supabaseClient, logger = console, table, schema
106
107
  // consume and return it without callers needing `as` casts. The
107
108
  // single widen-cast here replaces the casts every inner selector
108
109
  // would otherwise need.
109
- let q = fromTable().select(selectColumns);
110
- // Apply custom filters
111
- if (filterFn) {
112
- q = filterFn(q);
113
- }
114
- // Apply search if term is long enough
115
- if (searchTerm.length >= Math.max(minChars, 1)) {
116
- const escaped = searchTerm
117
- .replace(/\\/g, '\\\\')
118
- .replace(/"/g, '\\"')
119
- .replace(/,/g, '\\,')
120
- .replace(/\(/g, '\\(')
121
- .replace(/\)/g, '\\)');
122
- const term = `%${escaped}%`;
123
- const orConditions = searchColumns.map((col) => `${col}.ilike.${term}`).join(',');
124
- q = q.or(orConditions);
110
+ // A Supabase query builder is CONSUMED once awaited, so the query is built
111
+ // by a factory: the ordered attempt and the unordered fallback below each
112
+ // need their own instance.
113
+ const build = (withOrder) => {
114
+ // Supabase `.select()` returns a narrow `PostgrestTransformBuilder`
115
+ // subtype carrying the concrete row schema. We widen it to the
116
+ // schema-agnostic {@link EntitySelectorQuery} alias so the public
117
+ // `filterFn` prop type (unparameterised by design) can consume and
118
+ // return it without callers needing `as` casts.
119
+ let q = fromTable().select(selectColumns);
120
+ // Apply custom filters
121
+ if (filterFn) {
122
+ q = filterFn(q);
123
+ }
124
+ // Apply search if term is long enough
125
+ if (searchTerm.length >= Math.max(minChars, 1)) {
126
+ const escaped = searchTerm
127
+ .replace(/\\/g, '\\\\')
128
+ .replace(/"/g, '\\"')
129
+ .replace(/,/g, '\\,')
130
+ .replace(/\(/g, '\\(')
131
+ .replace(/\)/g, '\\)');
132
+ const term = `%${escaped}%`;
133
+ const orConditions = searchColumns.map((col) => `${col}.ilike.${term}`).join(',');
134
+ q = q.or(orConditions);
135
+ }
136
+ // ORDER BEFORE LIMIT. Without this the picker returns an arbitrary
137
+ // `limit`-sized slice of the matches, so a freshly created row is
138
+ // routinely absent from its own results.
139
+ if (withOrder && orderBy) {
140
+ q = q.order(orderBy, { ascending: orderAscending });
141
+ }
142
+ return q.limit(limit);
143
+ };
144
+ let { data, error: queryError } = await build(true);
145
+ // Fail SOFT on an unknown order column (Postgres 42703 / PostgREST
146
+ // PGRST204). `table` is dynamic at some call sites — a page-builder
147
+ // relationship widget or an admin data browser passes a table name from a
148
+ // registry — so the default `created_at` is not guaranteed to exist.
149
+ // Degrading to the previous unordered behaviour keeps those callers
150
+ // working; the ordering is an improvement, not a precondition.
151
+ if (queryError && orderBy) {
152
+ const code = queryError.code;
153
+ const msg = queryError.message ?? '';
154
+ if (code === '42703' || code === 'PGRST204' || msg.includes(orderBy)) {
155
+ logger.warn(`EntitySelector(${table}): order column "${orderBy}" is not present; ` +
156
+ `retrying UNORDERED. Results may omit recently created rows — pass an ` +
157
+ `explicit orderBy for this table to restore ordering.`);
158
+ ({ data, error: queryError } = await build(false));
159
+ }
125
160
  }
126
- q = q.limit(limit);
127
- const { data, error: queryError } = await q;
128
161
  if (queryError) {
129
162
  logger.warn(`EntitySelector(${table}): search error`, queryError.message);
130
163
  setError(queryError.message || 'Failed to load results.');
@@ -1 +1 @@
1
- {"version":3,"file":"error-boundary.d.ts","sourceRoot":"","sources":["../src/error-boundary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAEL,KAAK,4BAA4B,EAElC,MAAM,sBAAsB,CAAA;AAI7B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAA;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,cAAc,CAAC,EAAE,4BAA4B,CAAC,gBAAgB,CAAC,CAAA;IAC/D,OAAO,CAAC,EAAE,4BAA4B,CAAC,SAAS,CAAC,CAAA;IACjD,OAAO,CAAC,EAAE,4BAA4B,CAAC,SAAS,CAAC,CAAA;IACjD,SAAS,CAAC,EAAE,4BAA4B,CAAC,WAAW,CAAC,CAAA;IACrD,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AA0BD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,EACL,WAAW,EACX,gBAAgB,GACjB,EAAE,kBAAkB,+BA2CpB"}
1
+ {"version":3,"file":"error-boundary.d.ts","sourceRoot":"","sources":["../src/error-boundary.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAEL,KAAK,4BAA4B,EAElC,MAAM,sBAAsB,CAAA;AAI7B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAA;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,cAAc,CAAC,EAAE,4BAA4B,CAAC,gBAAgB,CAAC,CAAA;IAC/D,OAAO,CAAC,EAAE,4BAA4B,CAAC,SAAS,CAAC,CAAA;IACjD,OAAO,CAAC,EAAE,4BAA4B,CAAC,SAAS,CAAC,CAAA;IACjD,SAAS,CAAC,EAAE,4BAA4B,CAAC,WAAW,CAAC,CAAA;IACrD,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AA0BD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,EACL,WAAW,EACX,gBAAgB,GACjB,EAAE,kBAAkB,+BA2CpB"}
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx } from "react/jsx-runtime";
2
3
  import { ErrorBoundary as ReactErrorBoundary, } from 'react-error-boundary';
3
4
  import { Button } from './button.js';
@@ -0,0 +1,44 @@
1
+ /**
2
+ * useOnClickOutside
3
+ *
4
+ * Dismisses an open dropdown/menu/popover when the user clicks (or taps)
5
+ * outside of its container, or presses Escape.
6
+ *
7
+ * Why not a full-screen backdrop `<div>`? A `fixed inset-0` backdrop only
8
+ * reliably covers the whole viewport when none of its ancestors establish a
9
+ * new containing block for fixed-position descendants. `backdrop-filter`,
10
+ * `filter`, `transform`, and `will-change: transform` on an ancestor all do
11
+ * exactly that — and BSuite's glass-panel header chrome
12
+ * (`backdropFilter: blur(...)`) is one of them. A backdrop nested inside such
13
+ * an ancestor silently shrinks to that ancestor's box instead of the full
14
+ * page, so clicks on the rest of the page never reach it and the menu never
15
+ * closes. This is what broke click-outside dismissal for crm7's header
16
+ * tenant switchers (operator report, 2026-07-17) — see crm7's
17
+ * `TenantSwitcher.tsx` / `UserTenantSwitcher.tsx` / `CRM7Header.tsx`, the
18
+ * hook this one is promoted from.
19
+ *
20
+ * A `document`-level pointerdown listener sidesteps the problem entirely:
21
+ * JS event listeners are not affected by CSS stacking contexts or
22
+ * containing-block quirks, so this works regardless of what ancestors do.
23
+ *
24
+ * This is the canonical, shared version — promoted here so every consumer
25
+ * app (and every `@bsuite/*` package that depends on `@bsuite/ui`) gets one
26
+ * implementation instead of a fresh hand-rolled copy per app. crm7 carries
27
+ * its own pre-existing copy at `src/hooks/useClickOutside.ts`; that one is
28
+ * already correct and untouched by this promotion — a future consolidation
29
+ * onto this shared copy is a reasonable low-risk follow-up, not a bug fix.
30
+ *
31
+ * Usage:
32
+ * const containerRef = useRef<HTMLDivElement>(null);
33
+ * useOnClickOutside(containerRef, () => setIsOpen(false), isOpen);
34
+ *
35
+ * return (
36
+ * <div ref={containerRef} className="relative">
37
+ * <button onClick={() => setIsOpen((o) => !o)}>...</button>
38
+ * {isOpen && <div className="absolute ...">...menu...</div>}
39
+ * </div>
40
+ * );
41
+ */
42
+ import { type RefObject } from 'react';
43
+ export declare function useOnClickOutside<T extends HTMLElement>(ref: RefObject<T | null>, handler: () => void, enabled?: boolean): void;
44
+ //# sourceMappingURL=useOnClickOutside.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOnClickOutside.d.ts","sourceRoot":"","sources":["../../src/hooks/useOnClickOutside.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEjD,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW,EACrD,GAAG,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,EACxB,OAAO,EAAE,MAAM,IAAI,EACnB,OAAO,GAAE,OAAc,GACtB,IAAI,CAiCN"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * useOnClickOutside
3
+ *
4
+ * Dismisses an open dropdown/menu/popover when the user clicks (or taps)
5
+ * outside of its container, or presses Escape.
6
+ *
7
+ * Why not a full-screen backdrop `<div>`? A `fixed inset-0` backdrop only
8
+ * reliably covers the whole viewport when none of its ancestors establish a
9
+ * new containing block for fixed-position descendants. `backdrop-filter`,
10
+ * `filter`, `transform`, and `will-change: transform` on an ancestor all do
11
+ * exactly that — and BSuite's glass-panel header chrome
12
+ * (`backdropFilter: blur(...)`) is one of them. A backdrop nested inside such
13
+ * an ancestor silently shrinks to that ancestor's box instead of the full
14
+ * page, so clicks on the rest of the page never reach it and the menu never
15
+ * closes. This is what broke click-outside dismissal for crm7's header
16
+ * tenant switchers (operator report, 2026-07-17) — see crm7's
17
+ * `TenantSwitcher.tsx` / `UserTenantSwitcher.tsx` / `CRM7Header.tsx`, the
18
+ * hook this one is promoted from.
19
+ *
20
+ * A `document`-level pointerdown listener sidesteps the problem entirely:
21
+ * JS event listeners are not affected by CSS stacking contexts or
22
+ * containing-block quirks, so this works regardless of what ancestors do.
23
+ *
24
+ * This is the canonical, shared version — promoted here so every consumer
25
+ * app (and every `@bsuite/*` package that depends on `@bsuite/ui`) gets one
26
+ * implementation instead of a fresh hand-rolled copy per app. crm7 carries
27
+ * its own pre-existing copy at `src/hooks/useClickOutside.ts`; that one is
28
+ * already correct and untouched by this promotion — a future consolidation
29
+ * onto this shared copy is a reasonable low-risk follow-up, not a bug fix.
30
+ *
31
+ * Usage:
32
+ * const containerRef = useRef<HTMLDivElement>(null);
33
+ * useOnClickOutside(containerRef, () => setIsOpen(false), isOpen);
34
+ *
35
+ * return (
36
+ * <div ref={containerRef} className="relative">
37
+ * <button onClick={() => setIsOpen((o) => !o)}>...</button>
38
+ * {isOpen && <div className="absolute ...">...menu...</div>}
39
+ * </div>
40
+ * );
41
+ */
42
+ import { useEffect } from 'react';
43
+ export function useOnClickOutside(ref, handler, enabled = true) {
44
+ useEffect(() => {
45
+ // Only attach listeners while the menu is actually open — avoids
46
+ // unnecessary global listeners on every page.
47
+ if (!enabled)
48
+ return;
49
+ const handlePointerDown = (event) => {
50
+ const container = ref.current;
51
+ if (!container)
52
+ return;
53
+ if (event.target instanceof Node && container.contains(event.target)) {
54
+ // Click landed inside the container (trigger button or menu body) —
55
+ // let the component's own click handlers deal with it.
56
+ return;
57
+ }
58
+ handler();
59
+ };
60
+ const handleKeyDown = (event) => {
61
+ if (event.key === 'Escape')
62
+ handler();
63
+ };
64
+ // `pointerdown` fires before `click`, so the menu is already closed by
65
+ // the time a click on an element behind it fires — clicking "through"
66
+ // to another control outside the menu both closes the menu AND performs
67
+ // that control's own action, matching standard menu/popover UX.
68
+ document.addEventListener('pointerdown', handlePointerDown);
69
+ document.addEventListener('keydown', handleKeyDown);
70
+ return () => {
71
+ document.removeEventListener('pointerdown', handlePointerDown);
72
+ document.removeEventListener('keydown', handleKeyDown);
73
+ };
74
+ }, [ref, handler, enabled]);
75
+ }
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ export { LoadingSpinner, type LoadingSpinnerProps } from './loading-spinner.js';
13
13
  export { StatusBadge, type StatusBadgeProps, type StatusBadgeTone } from './status-badge.js';
14
14
  export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, } from './command.js';
15
15
  export { Popover, PopoverTrigger, PopoverContent } from './popover.js';
16
+ export { useOnClickOutside } from './hooks/useOnClickOutside.js';
16
17
  export { EntitySelector, type EntitySelectorProps, type EntitySelectorQuery, type EntitySelectorLogger, type EntitySelectorSupabaseClient, } from './entity-selector.js';
17
18
  export { BrandingCard, ColorEditorSheet, OklchColorPicker, type BrandingCardProps, type ColorEditorSheetProps, type OklchColorPickerProps, } from './branding/index.js';
18
19
  export { sanitizeCustomCss } from './branding/sanitizeCustomCss.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAA;AAC/B,OAAO,EACL,IAAI,EACJ,cAAc,EACd,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,OAAO,GACb,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC5E,OAAO,EACL,MAAM,EACN,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,aAAa,GACnB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,MAAM,EACN,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,SAAS,GACf,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC/E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAC5F,OAAO,EACL,OAAO,EACP,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACtE,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,GAClC,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAA;AAC/B,OAAO,EACL,IAAI,EACJ,cAAc,EACd,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,OAAO,GACb,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC5E,OAAO,EACL,MAAM,EACN,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,aAAa,GACnB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,MAAM,EACN,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,SAAS,GACf,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC/E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAC5F,OAAO,EACL,OAAO,EACP,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,GAClC,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA"}
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ export { LoadingSpinner } from './loading-spinner.js';
13
13
  export { StatusBadge } from './status-badge.js';
14
14
  export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, } from './command.js';
15
15
  export { Popover, PopoverTrigger, PopoverContent } from './popover.js';
16
+ export { useOnClickOutside } from './hooks/useOnClickOutside.js';
16
17
  export { EntitySelector, } from './entity-selector.js';
17
18
  // Branding components (v0.3.0+)
18
19
  export { BrandingCard, ColorEditorSheet, OklchColorPicker, } from './branding/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../src/popover.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAA;AAI3D,QAAA,MAAM,OAAO,yCAAwB,CAAA;AAErC,QAAA,MAAM,cAAc,gHAA2B,CAAA;AAE/C,QAAA,MAAM,cAAc,gKAgBlB,CAAA;AAGF,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAA"}
1
+ {"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../src/popover.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAA;AAI3D,QAAA,MAAM,OAAO,yCAAwB,CAAA;AAErC,QAAA,MAAM,cAAc,gHAA2B,CAAA;AAE/C,QAAA,MAAM,cAAc,gKAgBlB,CAAA;AAGF,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAA"}
package/dist/popover.js CHANGED
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx } from "react/jsx-runtime";
2
3
  import * as React from 'react';
3
4
  import * as PopoverPrimitive from '@radix-ui/react-popover';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsuite/ui",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {
@@ -79,6 +79,10 @@
79
79
  "import": "./dist/entity-selector.js",
80
80
  "types": "./dist/entity-selector.d.ts"
81
81
  },
82
+ "./use-on-click-outside": {
83
+ "import": "./dist/hooks/useOnClickOutside.js",
84
+ "types": "./dist/hooks/useOnClickOutside.d.ts"
85
+ },
82
86
  "./assets/d2c-default-logo.svg": "./src/assets/d2c-default-logo.svg"
83
87
  },
84
88
  "scripts": {
@@ -98,7 +102,7 @@
98
102
  "tailwind-merge": "^3.6.0"
99
103
  },
100
104
  "peerDependencies": {
101
- "@bsuite/theme": ">=0.7.0",
105
+ "@bsuite/theme": ">=0.7.0 <2",
102
106
  "@supabase/postgrest-js": "^2",
103
107
  "react": "^18.3.0 || ^19.0.0",
104
108
  "react-dom": "^18.3.0 || ^19.0.0"
@@ -112,7 +116,7 @@
112
116
  }
113
117
  },
114
118
  "devDependencies": {
115
- "@bsuite/theme": "^0.11.0",
119
+ "@bsuite/theme": "workspace:^",
116
120
  "@storybook/react-vite": "^10.5.8",
117
121
  "@supabase/postgrest-js": "^2.108.1",
118
122
  "@tailwindcss/vite": "^4.3.0",