@xh/hoist 71.0.0 → 72.0.0-SNAPSHOT.1736552780387

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/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Changelog
2
2
 
3
+ ## v72.0.0-SNAPSHOT - unreleased
4
+
3
5
  ## v71.0.0 - 2025-01-08
4
6
 
5
7
  ### 💥 Breaking Changes (upgrade difficulty: 🟠 MEDIUM - Hoist core update, import adjustments)
@@ -35,7 +35,6 @@ export const [DateEditor, dateEditor] = hoistCmp.withFactory<DateEditorProps>({
35
35
  ...props,
36
36
  inputProps: {
37
37
  rightElement: null,
38
-
39
38
  enablePicker: !!portalContainer,
40
39
  showPickerOnFocus: !!portalContainer,
41
40
  portalContainer,
@@ -5,35 +5,46 @@
5
5
  * Copyright © 2025 Extremely Heavy Industries Inc.
6
6
  */
7
7
 
8
- .xh-date-input {
9
- // Style input in picker-only mode
10
- &--picker-only {
11
- input {
12
- color: var(--xh-input-text-color) !important;
13
- background-color: var(--xh-input-bg) !important;
14
- cursor: pointer !important;
15
- }
16
-
17
- .bp5-input-group.bp5-disabled {
18
- cursor: pointer !important;
19
- }
8
+ .xh-date-input__wrapper {
9
+ .bp5-input-action {
10
+ height: 100%;
20
11
  }
21
12
 
22
- // Style picker icon in input-only mode
23
- &__picker-icon--disabled:hover {
24
- background-color: transparent !important;
25
- cursor: not-allowed;
13
+ .bp5-input-group .xh-icon {
14
+ position: relative;
15
+ margin: 0 !important;
26
16
  }
27
17
 
28
- // Style buttons when disabled
29
- &.xh-input-disabled:not(.xh-date-input--picker-only) button:hover {
30
- background-color: transparent !important;
31
- cursor: not-allowed;
32
- }
18
+ .xh-date-input {
19
+ // Style input in picker-only mode
20
+ &--picker-only {
21
+ input {
22
+ color: var(--xh-input-text-color) !important;
23
+ background-color: var(--xh-input-bg) !important;
24
+ cursor: pointer !important;
25
+ }
26
+
27
+ .bp5-input-group.bp5-disabled {
28
+ cursor: pointer !important;
29
+ }
30
+ }
33
31
 
34
- // Prevent browser from capturing click events when input is disabled due to use of
35
- // enableTextInput: false prop. See https://github.com/xh/hoist-react/issues/3460
36
- input[disabled] {
37
- pointer-events: none;
32
+ // Style picker icon in input-only mode
33
+ &__picker-icon--disabled:hover {
34
+ background-color: transparent !important;
35
+ cursor: not-allowed;
36
+ }
37
+
38
+ // Style buttons when disabled
39
+ &.xh-input-disabled:not(.xh-date-input--picker-only) button:hover {
40
+ background-color: transparent !important;
41
+ cursor: not-allowed;
42
+ }
43
+
44
+ // Prevent browser from capturing click events when input is disabled due to use of
45
+ // enableTextInput: false prop. See https://github.com/xh/hoist-react/issues/3460
46
+ input[disabled] {
47
+ pointer-events: none;
48
+ }
38
49
  }
39
50
  }
@@ -8,9 +8,9 @@ import {PopperBoundary, PopperModifierOverrides} from '@blueprintjs/core';
8
8
  import {TimePickerProps} from '@blueprintjs/datetime';
9
9
  import {ReactDayPickerSingleProps} from '@blueprintjs/datetime2/src/common/reactDayPickerProps';
10
10
  import {HoistInputModel, HoistInputProps, useHoistInputModel} from '@xh/hoist/cmp/input';
11
- import {div} from '@xh/hoist/cmp/layout';
11
+ import {div, hbox} from '@xh/hoist/cmp/layout';
12
12
  import {hoistCmp, HoistProps, HSide, LayoutProps, Some} from '@xh/hoist/core';
13
- import {button, buttonGroup} from '@xh/hoist/desktop/cmp/button';
13
+ import {button} from '@xh/hoist/desktop/cmp/button';
14
14
  import {textInput, TextInputModel} from '@xh/hoist/desktop/cmp/input';
15
15
  import '@xh/hoist/desktop/register';
16
16
  import {fmtDate} from '@xh/hoist/format';
@@ -19,10 +19,10 @@ import {datePicker as bpDatePicker, popover, Position} from '@xh/hoist/kit/bluep
19
19
  import {bindable, makeObservable} from '@xh/hoist/mobx';
20
20
  import {wait} from '@xh/hoist/promise';
21
21
  import {isLocalDate, LocalDate} from '@xh/hoist/utils/datetime';
22
- import {consumeEvent, getTestId, warnIf, withDefault} from '@xh/hoist/utils/js';
22
+ import {consumeEvent, getTestId, withDefault} from '@xh/hoist/utils/js';
23
23
  import {getLayoutProps} from '@xh/hoist/utils/react';
24
24
  import classNames from 'classnames';
25
- import {assign, castArray, clone, trim} from 'lodash';
25
+ import {assign, castArray, clone, isEmpty, trim} from 'lodash';
26
26
  import moment from 'moment';
27
27
  import {createRef, ReactElement, ReactNode} from 'react';
28
28
  import './DateInput.scss';
@@ -375,44 +375,11 @@ class DateInputModel extends HoistInputModel {
375
375
 
376
376
  const cmp = hoistCmp.factory<DateInputProps & {model: DateInputModel}>(
377
377
  ({model, className, ...props}, ref) => {
378
- warnIf(
379
- (props.enableClear || props.enablePicker) && props.rightElement,
380
- 'Cannot specify enableClear or enablePicker along with custom rightElement - built-in clear/picker button will not be shown.'
381
- );
382
-
383
378
  const enablePicker = props.enablePicker ?? true,
384
379
  enableTextInput = props.enableTextInput ?? true,
385
- enableClear = props.enableClear ?? false,
386
380
  disabled = props.disabled ?? false,
387
- isClearable = model.internalValue !== null,
388
381
  isOpen = enablePicker && model.popoverOpen && !disabled;
389
382
 
390
- const buttons = buttonGroup({
391
- padding: 0,
392
- items: [
393
- button({
394
- className: 'xh-date-input__clear-icon',
395
- omit: !enableClear || !isClearable || disabled,
396
- icon: Icon.cross(),
397
- tabIndex: -1,
398
- onClick: model.onClearBtnClick,
399
- testId: getTestId(props, 'clear')
400
- }),
401
- button({
402
- className: classNames(
403
- 'xh-date-input__picker-icon',
404
- enablePicker ? null : 'xh-date-input__picker-icon--disabled'
405
- ),
406
- icon: Icon.calendar(),
407
- tabIndex: enableTextInput || disabled ? -1 : undefined,
408
- ref: model.buttonRef,
409
- onClick: enablePicker && !disabled ? model.onOpenPopoverClick : null,
410
- testId: getTestId(props, 'picker')
411
- })
412
- ]
413
- });
414
- const rightElement = withDefault(props.rightElement, buttons);
415
-
416
383
  let {minDate, maxDate, initialMonth, renderValue} = model;
417
384
 
418
385
  // If app has set an out-of-range date, we render it -- these bounds govern *manual* entry
@@ -475,9 +442,15 @@ const cmp = hoistCmp.factory<DateInputProps & {model: DateInputModel}>(
475
442
  onCommit: model.onInputCommit,
476
443
  onChange: model.onInputChange,
477
444
  onKeyDown: model.onInputKeyDown,
478
- rightElement: rightElement as ReactElement,
479
445
  disabled: disabled || !enableTextInput,
480
446
  leftIcon: props.leftIcon,
447
+ rightElement: rightIcons({
448
+ model,
449
+ ...props,
450
+ disabled,
451
+ enableTextInput,
452
+ enablePicker
453
+ }),
481
454
  tabIndex: props.tabIndex,
482
455
  placeholder: props.placeholder,
483
456
  textAlign: props.textAlign,
@@ -498,3 +471,44 @@ const cmp = hoistCmp.factory<DateInputProps & {model: DateInputModel}>(
498
471
  });
499
472
  }
500
473
  );
474
+
475
+ const rightIcons = hoistCmp.factory<DateInputModel>({
476
+ render({model, disabled, enableTextInput, enablePicker, ...props}) {
477
+ const buttonLayoutProps = {padding: 0, margin: 0, height: '100%'},
478
+ enableClear = props.enableClear ?? false,
479
+ isClearable = model.internalValue !== null,
480
+ items = [];
481
+
482
+ // 1) First potential icon is clear button
483
+ if (enableClear && isClearable && !disabled) {
484
+ items.push(
485
+ button({
486
+ className: 'xh-date-input__clear-icon',
487
+ icon: Icon.cross(),
488
+ tabIndex: -1,
489
+ onClick: model.onClearBtnClick,
490
+ testId: getTestId(props, 'clear'),
491
+ ...buttonLayoutProps
492
+ })
493
+ );
494
+ }
495
+
496
+ // 2) Second potential icon is app-specified, or default calendar icon. Set prop to null to hide.
497
+ const rightElement = withDefault(
498
+ props.rightElement,
499
+ button({
500
+ className: 'xh-date-input__picker-icon',
501
+ icon: Icon.calendar(),
502
+ tabIndex: enableTextInput || disabled ? -1 : undefined,
503
+ onClick: enablePicker && !disabled ? model.onOpenPopoverClick : null,
504
+ testId: getTestId(props, 'picker'),
505
+ disabled,
506
+ ref: model.buttonRef,
507
+ ...buttonLayoutProps
508
+ })
509
+ );
510
+ if (rightElement) items.push(rightElement);
511
+
512
+ return hbox({height: '100%', paddingRight: 3, items, omit: isEmpty(items)});
513
+ }
514
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xh/hoist",
3
- "version": "71.0.0",
3
+ "version": "72.0.0-SNAPSHOT.1736552780387",
4
4
  "description": "Hoist add-on for building and deploying React Applications.",
5
5
  "repository": "github:xh/hoist-react",
6
6
  "homepage": "https://xh.io",