@xh/hoist 86.2.0 → 86.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.
Files changed (66) hide show
  1. package/.gitattributes +4 -0
  2. package/CHANGELOG.md +58 -0
  3. package/admin/AppModel.ts +3 -4
  4. package/admin/tabs/activity/tracking/ActivityTrackingModel.ts +56 -6
  5. package/admin/tabs/activity/tracking/ActivityTrackingPanel.ts +9 -26
  6. package/admin/tabs/clients/ClientsModel.ts +4 -1
  7. package/admin/tabs/clients/activity/ClientDetailModel.ts +5 -1
  8. package/admin/tabs/userData/roles/RolePanel.ts +2 -2
  9. package/appcontainer/RouterModel.ts +6 -6
  10. package/build/types/admin/AppModel.d.ts +3 -4
  11. package/build/types/admin/tabs/activity/tracking/ActivityTrackingModel.d.ts +14 -3
  12. package/build/types/admin/tabs/clients/ClientsModel.d.ts +3 -0
  13. package/build/types/appcontainer/RouterModel.d.ts +5 -5
  14. package/build/types/cmp/grid/Grid.d.ts +2 -1
  15. package/build/types/cmp/grid/GridModel.d.ts +2 -2
  16. package/build/types/cmp/grid/Types.d.ts +8 -1
  17. package/build/types/cmp/input/SegmentedControlOption.d.ts +12 -0
  18. package/build/types/core/HoistAppModel.d.ts +2 -3
  19. package/build/types/core/types/Types.d.ts +12 -0
  20. package/build/types/desktop/cmp/filter/FilterChooser.d.ts +5 -0
  21. package/build/types/desktop/cmp/filter/PopoverFilterChooser.d.ts +3 -1
  22. package/build/types/desktop/cmp/grid/impl/colchooser/ColChooserModel.d.ts +2 -2
  23. package/build/types/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomRowModel.d.ts +9 -1
  24. package/build/types/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomTabModel.d.ts +8 -2
  25. package/build/types/desktop/cmp/input/Select.d.ts +8 -0
  26. package/build/types/kit/react-dropzone/index.d.ts +1 -0
  27. package/build/types/kit/swiper/index.d.ts +4 -3
  28. package/build/types/mobile/cmp/grid/impl/ColChooserModel.d.ts +2 -2
  29. package/build/types/mobile/cmp/input/Select.d.ts +8 -0
  30. package/cmp/grid/Grid.ts +10 -2
  31. package/cmp/grid/GridModel.ts +4 -3
  32. package/cmp/grid/Types.ts +9 -1
  33. package/cmp/grid/impl/MenuSupport.ts +1 -1
  34. package/cmp/input/SegmentedControlOption.ts +14 -0
  35. package/cmp/store/impl/StoreFilterFieldImplModel.ts +5 -6
  36. package/core/HoistAppModel.ts +2 -3
  37. package/core/types/Types.ts +14 -5
  38. package/desktop/cmp/filechooser/FileChooser.ts +6 -3
  39. package/desktop/cmp/filechooser/FileChooserModel.ts +12 -5
  40. package/desktop/cmp/filter/FilterChooser.scss +41 -0
  41. package/desktop/cmp/filter/FilterChooser.ts +147 -7
  42. package/desktop/cmp/filter/PopoverFilterChooser.ts +7 -84
  43. package/desktop/cmp/grid/editors/impl/InlineEditorModel.ts +6 -1
  44. package/desktop/cmp/grid/find/impl/GridFindFieldImplModel.ts +3 -5
  45. package/desktop/cmp/grid/impl/colchooser/ColChooserModel.ts +2 -2
  46. package/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomRow.ts +12 -12
  47. package/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomRowModel.ts +18 -0
  48. package/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomTab.scss +5 -0
  49. package/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomTab.ts +13 -2
  50. package/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomTabModel.ts +97 -14
  51. package/desktop/cmp/input/SegmentedControl.ts +7 -3
  52. package/desktop/cmp/input/Select.ts +24 -16
  53. package/docs/routing.md +4 -2
  54. package/docs/upgrade-notes/v86-upgrade-notes.md +73 -8
  55. package/kit/react-dropzone/index.ts +1 -0
  56. package/mcp/README.md +12 -0
  57. package/mcp/data/ts-registry.spec.ts +156 -0
  58. package/mcp/data/ts-registry.ts +13 -6
  59. package/mcp/formatters/typescript.ts +7 -3
  60. package/mcp/util/paths.ts +21 -0
  61. package/mobile/cmp/grid/impl/ColChooserModel.ts +2 -2
  62. package/mobile/cmp/input/SegmentedControl.ts +7 -3
  63. package/mobile/cmp/input/Select.ts +21 -15
  64. package/mobx/README.md +2 -1
  65. package/package.json +5 -5
  66. package/desktop/cmp/filter/PopoverFilterChooser.scss +0 -42
@@ -21,7 +21,7 @@ import {action, bindable, makeObservable, observable, override} from '@xh/hoist/
21
21
  import {debouncePromise, wait} from '@xh/hoist/promise';
22
22
  import {throwIf, withDefault, mergeDeep} from '@xh/hoist/utils/js';
23
23
  import {createObservableRef, getLayoutProps} from '@xh/hoist/utils/react';
24
- import {escapeRegExp, isEqual, isNil, isPlainObject, keyBy} from 'lodash';
24
+ import {escapeRegExp, isEqual, isNil, isPlainObject, unionWith} from 'lodash';
25
25
  import {Children, ReactNode, ReactPortal} from 'react';
26
26
  import ReactDom from 'react-dom';
27
27
  import './Select.scss';
@@ -157,6 +157,15 @@ export interface SelectProps extends HoistProps, HoistInputProps, LayoutProps {
157
157
 
158
158
  /** Field on provided options for sourcing each option's value (default `value`). */
159
159
  valueField?: string;
160
+
161
+ /**
162
+ * Function to generate a `SelectOption` for a (non-null) selected value not present in the
163
+ * current options list. Return null to fall back to the default value-as-label behavior.
164
+ *
165
+ * Useful with queryFn-based selects, readonly forms, or any case where options may not be
166
+ * loaded when a value is set, ensuring the value renders with its proper label.
167
+ */
168
+ generateOptionFn?: (value: any) => SelectOption;
160
169
  }
161
170
 
162
171
  /**
@@ -377,7 +386,8 @@ class SelectInputModel extends HoistInputModel {
377
386
 
378
387
  // Convert external value into option object(s). Options created if missing - this takes the
379
388
  // external value from the model, and we will respect that even if we don't know about it.
380
- // (Exception for a null value, which we will only accept if explicitly present in options.)
389
+ // (Exception for a null value, which is never synthesized - accepted only if provided via
390
+ // options.)
381
391
  override toInternal(external) {
382
392
  return this.findOption(external, !isNil(external));
383
393
  }
@@ -393,7 +403,10 @@ class SelectInputModel extends HoistInputModel {
393
403
  }
394
404
  }
395
405
 
396
- return createIfNotFound ? this.valueToOption(value) : null;
406
+ if (!createIfNotFound) return null;
407
+
408
+ // Value not among options - let the app generate an option for it, else synthesize one.
409
+ return this.componentProps.generateOptionFn?.(value) ?? this.valueToOption(value);
397
410
  }
398
411
 
399
412
  override toExternal(internal) {
@@ -453,15 +466,9 @@ class SelectInputModel extends HoistInputModel {
453
466
 
454
467
  // Carry forward and add to any existing internalOpts to allow our value
455
468
  // converters to continue all selected values in multiMode.
456
- const matchesByVal = keyBy(matchOpts, 'value'),
457
- newOpts = [...matchOpts];
458
-
459
- this.internalOptions.forEach(currOpt => {
460
- const matchOpt = matchesByVal[currOpt.value];
461
- if (!matchOpt) newOpts.push(currOpt); // avoiding dupes
462
- });
463
-
464
- this.internalOptions = newOpts;
469
+ this.internalOptions = unionWith(matchOpts, this.internalOptions, (a, b) =>
470
+ isEqual(a.value, b.value)
471
+ );
465
472
 
466
473
  // But only return the matching options back to the combo.
467
474
  return matchOpts;
@@ -484,8 +491,7 @@ class SelectInputModel extends HoistInputModel {
484
491
  // Option Rendering
485
492
  //----------------------
486
493
  formatOptionLabel = (opt, params) => {
487
- // Always display the standard label string in the value container (context == 'value').
488
- // If we need to expose customization here, we could consider a dedicated prop.
494
+ // Display the standard label string in the value container (context == 'value').
489
495
  if (params.context !== 'menu') {
490
496
  return opt.label;
491
497
  }
@@ -501,7 +507,7 @@ class SelectInputModel extends HoistInputModel {
501
507
  return div(opt.label);
502
508
  }
503
509
 
504
- return this.externalValue === opt.value
510
+ return isEqual(this.externalValue, opt.value)
505
511
  ? hbox({
506
512
  items: [
507
513
  div({
package/mobx/README.md CHANGED
@@ -45,7 +45,8 @@ The following are re-exported from MobX and mobx-react-lite:
45
45
 
46
46
  The package configures MobX with `enforceActions: 'observed'`, meaning any modification to
47
47
  an observable property that is currently being observed must occur inside an `@action` method,
48
- `runInAction()` block, or `@bindable` setter. MobX logs a warning if this rule is violated.
48
+ `runInAction()` block, `@bindable` setter, or a `reaction`/`when` run callback (MobX
49
+ auto-wraps these in an action). MobX logs a warning if this rule is violated.
49
50
 
50
51
  This enforcement prevents accidental state mutations and makes data flow predictable.
51
52
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xh/hoist",
3
- "version": "86.2.0",
3
+ "version": "86.3.0",
4
4
  "description": "Hoist add-on for building and deploying React Applications.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -38,8 +38,8 @@
38
38
  ]
39
39
  },
40
40
  "dependencies": {
41
- "@auth0/auth0-spa-js": "~2.21.1",
42
- "@azure/msal-browser": "~5.14.0",
41
+ "@auth0/auth0-spa-js": "~2.23.0",
42
+ "@azure/msal-browser": "~5.16.0",
43
43
  "@blueprintjs/core": "^6.3.2",
44
44
  "@blueprintjs/datetime": "^6.0.6",
45
45
  "@codemirror/commands": "^6.10.3",
@@ -90,7 +90,7 @@
90
90
  "semver": "~7.8.0",
91
91
  "short-unique-id": "~5.3.2",
92
92
  "store2": "~2.14.3",
93
- "swiper": "^12.1.2",
93
+ "swiper": "^14.0.0",
94
94
  "ts-morph": "^27.0.2",
95
95
  "tsx": "^4.21.0",
96
96
  "ua-parser-js": "~2.0.4",
@@ -118,7 +118,7 @@
118
118
  "react-dom": "~18.2.0",
119
119
  "stylelint": "17.x",
120
120
  "stylelint-config-standard-scss": "17.x",
121
- "type-fest": "4.x",
121
+ "type-fest": "5.x",
122
122
  "typescript": "~5.9.3"
123
123
  },
124
124
  "resolutions": {
@@ -1,42 +0,0 @@
1
- /*
2
- * This file belongs to Hoist, an application development toolkit
3
- * developed by Extremely Heavy Industries (www.xh.io | info@xh.io)
4
- *
5
- * Copyright © 2026 Extremely Heavy Industries Inc.
6
- */
7
- .xh-popover-filter-chooser {
8
- & > .bp6-popover-target {
9
- display: flex;
10
- flex: 1;
11
- }
12
-
13
- // Extra class names required to override the default styles of the popover
14
- &__popover.bp6-popover.bp6-minimal {
15
- margin-top: -15px !important;
16
- box-shadow: none;
17
-
18
- .bp6-popover-content {
19
- background: transparent;
20
- }
21
-
22
- .xh-select__value-container--is-multi {
23
- height: unset;
24
- line-height: unset;
25
- }
26
- }
27
-
28
- &__filter-chooser {
29
- .xh-select__value-container--is-multi {
30
- overflow-y: hidden !important;
31
- }
32
-
33
- .xh-select {
34
- .xh-select__control--is-disabled {
35
- background: var(--xh-input-bg);
36
- }
37
- .xh-select__multi-value--is-disabled .xh-select__multi-value__label {
38
- color: unset;
39
- }
40
- }
41
- }
42
- }