@pallasoft/ps-input-components 2.1.0 → 3.0.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 (136) hide show
  1. package/dist/components/ps-calendar-header.js +4 -7
  2. package/dist/components/ps-cascader-input.js +1 -1
  3. package/dist/components/ps-checkbox-matrix.d.ts +13 -0
  4. package/dist/components/ps-checkbox-matrix.js +24 -0
  5. package/dist/components/ps-color-picker.js +2 -2
  6. package/dist/components/ps-combobox-input.js +1 -1
  7. package/dist/components/ps-date-input.js +1 -1
  8. package/dist/components/ps-date-preset-field.js +2 -2
  9. package/dist/components/ps-field-skeleton.js +1 -1
  10. package/dist/components/ps-file-picker.js +1 -1
  11. package/dist/components/ps-multi-select-input.js +2 -2
  12. package/dist/components/ps-phone-input.js +1 -1
  13. package/dist/components/ps-portable-text-editor.d.ts +1 -1
  14. package/dist/components/ps-portable-text-editor.js +1 -2
  15. package/dist/components/ps-portable-text-link-dialog.d.ts +2 -1
  16. package/dist/components/ps-portable-text-link-dialog.js +2 -2
  17. package/dist/components/ps-portable-text-toolbar.js +2 -7
  18. package/dist/components/ps-select-input.js +1 -1
  19. package/dist/components/ps-toggle.js +1 -1
  20. package/dist/components/ps-year-input.js +1 -1
  21. package/dist/constants/ps-calendar-header-classes.d.ts +6 -0
  22. package/dist/constants/ps-calendar-header-classes.js +9 -0
  23. package/dist/constants/ps-portable-text-editor-config.d.ts +10 -2
  24. package/dist/constants/ps-portable-text-editor-config.js +10 -2
  25. package/dist/esm/components/ps-calendar-header.js +4 -7
  26. package/dist/esm/components/ps-cascader-input.js +1 -1
  27. package/dist/esm/components/ps-checkbox-matrix.js +20 -0
  28. package/dist/esm/components/ps-color-picker.js +2 -2
  29. package/dist/esm/components/ps-combobox-input.js +1 -1
  30. package/dist/esm/components/ps-date-input.js +1 -1
  31. package/dist/esm/components/ps-date-preset-field.js +2 -2
  32. package/dist/esm/components/ps-field-skeleton.js +1 -1
  33. package/dist/esm/components/ps-file-picker.js +1 -1
  34. package/dist/esm/components/ps-multi-select-input.js +2 -2
  35. package/dist/esm/components/ps-phone-input.js +1 -1
  36. package/dist/esm/components/ps-portable-text-editor.js +1 -2
  37. package/dist/esm/components/ps-portable-text-link-dialog.js +2 -2
  38. package/dist/esm/components/ps-portable-text-toolbar.js +2 -7
  39. package/dist/esm/components/ps-select-input.js +1 -1
  40. package/dist/esm/components/ps-toggle.js +1 -1
  41. package/dist/esm/components/ps-year-input.js +1 -1
  42. package/dist/esm/constants/ps-calendar-header-classes.js +6 -0
  43. package/dist/esm/constants/ps-portable-text-editor-config.js +10 -2
  44. package/dist/esm/index.js +7 -0
  45. package/dist/esm/interfaces/ps-checkbox-matrix-cell.js +1 -0
  46. package/dist/esm/interfaces/ps-checkbox-matrix-column.js +1 -0
  47. package/dist/esm/interfaces/ps-checkbox-matrix-group.js +1 -0
  48. package/dist/esm/interfaces/ps-checkbox-matrix-labels.js +1 -0
  49. package/dist/esm/interfaces/ps-checkbox-matrix-row.js +1 -0
  50. package/dist/esm/portable-text-core/components/ps-portable-text-core-editor-stub.js +2 -0
  51. package/dist/esm/portable-text-core/components/ps-portable-text-core-editor.js +64 -0
  52. package/dist/esm/portable-text-core/components/ps-portable-text-core.js +5 -26
  53. package/dist/esm/portable-text-core/constants/ps-portable-text-core-config.js +29 -9
  54. package/dist/esm/portable-text-core/contexts/ps-portable-text-core-context.js +9 -0
  55. package/dist/esm/portable-text-core/hooks/use-ps-portable-text-link-form.js +11 -5
  56. package/dist/esm/portable-text-core/hooks/use-ps-portable-text-toolbar.js +17 -49
  57. package/dist/esm/portable-text-core/index.js +4 -0
  58. package/dist/esm/portable-text-core/interfaces/ps-portable-text-active-formats.js +1 -0
  59. package/dist/esm/portable-text-core/interfaces/ps-portable-text-block-draft.js +1 -0
  60. package/dist/esm/portable-text-core/interfaces/ps-portable-text-core-class-names.js +1 -0
  61. package/dist/esm/portable-text-core/interfaces/ps-portable-text-core-context-data.js +1 -0
  62. package/dist/esm/portable-text-core/interfaces/ps-portable-text-core-props.js +1 -0
  63. package/dist/esm/portable-text-core/interfaces/ps-portable-text-extension-options.js +1 -0
  64. package/dist/esm/portable-text-core/interfaces/ps-portable-text-span-draft.js +1 -0
  65. package/dist/esm/portable-text-core/interfaces/ps-portable-text-toolbar-state.js +1 -0
  66. package/dist/esm/portable-text-core/services/ps-portable-text-command-service.js +73 -0
  67. package/dist/esm/portable-text-core/services/ps-portable-text-converter-service.js +196 -0
  68. package/dist/esm/portable-text-core/services/ps-portable-text-editor-service.js +4 -0
  69. package/dist/esm/portable-text-core/services/ps-portable-text-extension-service.js +89 -0
  70. package/dist/esm/portable-text-engine/index.js +1 -0
  71. package/dist/esm/portable-text-engine/worker.js +1 -0
  72. package/dist/esm/services/ps-checkbox-matrix-service.js +28 -0
  73. package/dist/index.d.ts +7 -0
  74. package/dist/index.js +7 -0
  75. package/dist/interfaces/ps-checkbox-matrix-cell.d.ts +6 -0
  76. package/dist/interfaces/ps-checkbox-matrix-cell.js +2 -0
  77. package/dist/interfaces/ps-checkbox-matrix-column.d.ts +5 -0
  78. package/dist/interfaces/ps-checkbox-matrix-column.js +2 -0
  79. package/dist/interfaces/ps-checkbox-matrix-group.d.ts +6 -0
  80. package/dist/interfaces/ps-checkbox-matrix-group.js +2 -0
  81. package/dist/interfaces/ps-checkbox-matrix-labels.d.ts +9 -0
  82. package/dist/interfaces/ps-checkbox-matrix-labels.js +2 -0
  83. package/dist/interfaces/ps-checkbox-matrix-row.d.ts +6 -0
  84. package/dist/interfaces/ps-checkbox-matrix-row.js +2 -0
  85. package/dist/portable-text/index.d.ts +1 -1
  86. package/dist/portable-text-core/components/ps-portable-text-core-editor-stub.d.ts +2 -0
  87. package/dist/portable-text-core/components/ps-portable-text-core-editor-stub.js +6 -0
  88. package/dist/portable-text-core/components/ps-portable-text-core-editor.d.ts +2 -0
  89. package/dist/portable-text-core/components/ps-portable-text-core-editor.js +68 -0
  90. package/dist/portable-text-core/components/ps-portable-text-core.d.ts +2 -17
  91. package/dist/portable-text-core/components/ps-portable-text-core.js +3 -24
  92. package/dist/portable-text-core/constants/ps-portable-text-core-config.d.ts +36 -19
  93. package/dist/portable-text-core/constants/ps-portable-text-core-config.js +29 -9
  94. package/dist/portable-text-core/contexts/ps-portable-text-core-context.d.ts +2 -0
  95. package/dist/portable-text-core/contexts/ps-portable-text-core-context.js +12 -0
  96. package/dist/portable-text-core/hooks/use-ps-portable-text-link-form.d.ts +3 -1
  97. package/dist/portable-text-core/hooks/use-ps-portable-text-link-form.js +10 -4
  98. package/dist/portable-text-core/hooks/use-ps-portable-text-toolbar.d.ts +5 -10
  99. package/dist/portable-text-core/hooks/use-ps-portable-text-toolbar.js +17 -49
  100. package/dist/portable-text-core/index.d.ts +5 -1
  101. package/dist/portable-text-core/index.js +4 -0
  102. package/dist/portable-text-core/interfaces/ps-portable-text-active-formats.d.ts +10 -0
  103. package/dist/portable-text-core/interfaces/ps-portable-text-active-formats.js +2 -0
  104. package/dist/portable-text-core/interfaces/ps-portable-text-block-draft.d.ts +7 -0
  105. package/dist/portable-text-core/interfaces/ps-portable-text-block-draft.js +2 -0
  106. package/dist/portable-text-core/interfaces/ps-portable-text-core-class-names.d.ts +8 -0
  107. package/dist/portable-text-core/interfaces/ps-portable-text-core-class-names.js +2 -0
  108. package/dist/portable-text-core/interfaces/ps-portable-text-core-context-data.d.ts +9 -0
  109. package/dist/portable-text-core/interfaces/ps-portable-text-core-context-data.js +2 -0
  110. package/dist/portable-text-core/interfaces/ps-portable-text-core-props.d.ts +16 -0
  111. package/dist/portable-text-core/interfaces/ps-portable-text-core-props.js +2 -0
  112. package/dist/portable-text-core/interfaces/ps-portable-text-editor-labels.d.ts +1 -0
  113. package/dist/portable-text-core/interfaces/ps-portable-text-extension-options.d.ts +6 -0
  114. package/dist/portable-text-core/interfaces/ps-portable-text-extension-options.js +2 -0
  115. package/dist/portable-text-core/interfaces/ps-portable-text-span-draft.d.ts +4 -0
  116. package/dist/portable-text-core/interfaces/ps-portable-text-span-draft.js +2 -0
  117. package/dist/portable-text-core/interfaces/ps-portable-text-toolbar-state.d.ts +5 -0
  118. package/dist/portable-text-core/interfaces/ps-portable-text-toolbar-state.js +2 -0
  119. package/dist/portable-text-core/services/ps-portable-text-command-service.d.ts +14 -0
  120. package/dist/portable-text-core/services/ps-portable-text-command-service.js +77 -0
  121. package/dist/portable-text-core/services/ps-portable-text-converter-service.d.ts +18 -0
  122. package/dist/portable-text-core/services/ps-portable-text-converter-service.js +200 -0
  123. package/dist/portable-text-core/services/ps-portable-text-editor-service.d.ts +1 -0
  124. package/dist/portable-text-core/services/ps-portable-text-editor-service.js +4 -0
  125. package/dist/portable-text-core/services/ps-portable-text-extension-service.d.ts +8 -0
  126. package/dist/portable-text-core/services/ps-portable-text-extension-service.js +93 -0
  127. package/dist/portable-text-engine/index.d.ts +1 -0
  128. package/dist/portable-text-engine/index.js +17 -0
  129. package/dist/portable-text-engine/worker.d.ts +1 -0
  130. package/dist/portable-text-engine/worker.js +17 -0
  131. package/dist/services/ps-checkbox-matrix-service.d.ts +9 -0
  132. package/dist/services/ps-checkbox-matrix-service.js +32 -0
  133. package/package.json +30 -6
  134. package/dist/constants/ps-portable-text-editor-renderers.d.ts +0 -6
  135. package/dist/constants/ps-portable-text-editor-renderers.js +0 -32
  136. package/dist/esm/constants/ps-portable-text-editor-renderers.js +0 -29
@@ -35,7 +35,7 @@ export const PsColorPicker = ({ className, disabled, helperText, hideLabel, labe
35
35
  saturation: Math.round((x / bounds.width) * 100),
36
36
  }));
37
37
  };
38
- return (_jsxs("div", { className: PallasoftClassNameService.merge('flex flex-col gap-2', className), children: [hideLabel ? null : _jsx("span", { className: 'ps-input-label block', children: label }), _jsxs(DialogTrigger, { children: [_jsxs(Button, { "aria-label": hideLabel ? label : undefined, className: 'ps-input-control ps-focus-ring flex min-h-11 w-full items-center gap-3 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', isDisabled: disabled, children: [_jsx("span", { className: 'h-6 w-6 shrink-0 rounded-md border border-line', style: { backgroundColor: swatchColor ? swatchColor : 'transparent' } }), _jsx("span", { className: 'font-mono text-sm uppercase', children: swatchColor ? swatchColor : 'Pick a colour' }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'ml-auto block h-4 w-4 shrink-0 text-primary', iconKey: PsIconKey.Chevron })] }), _jsx(Popover, { className: 'ps-floating-panel w-[min(calc(100vw-2rem),18rem)] outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsxs(Dialog, { "aria-label": label, className: 'flex flex-col gap-3 p-3 outline-none', children: [_jsx("div", { className: 'relative h-36 w-full cursor-crosshair rounded-ps-control', onPointerDown: (event) => {
38
+ return (_jsxs("div", { className: PallasoftClassNameService.merge('flex flex-col gap-2', className), children: [hideLabel ? null : _jsx("span", { className: 'ps-input-label block', children: label }), _jsxs(DialogTrigger, { children: [_jsxs(Button, { "aria-label": hideLabel ? label : undefined, className: 'ps-input-control ps-focus-ring flex w-full items-center gap-3 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', isDisabled: disabled, children: [_jsx("span", { className: 'h-6 w-6 shrink-0 rounded-md border border-line', style: { backgroundColor: swatchColor ? swatchColor : 'transparent' } }), _jsx("span", { className: 'font-mono text-sm uppercase', children: swatchColor ? swatchColor : 'Pick a colour' }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'ml-auto block h-4 w-4 shrink-0 text-primary', iconKey: PsIconKey.Chevron })] }), _jsx(Popover, { className: 'ps-floating-panel w-[min(calc(100vw-2rem),18rem)] outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsxs(Dialog, { "aria-label": label, className: 'flex flex-col gap-3 p-3 outline-none', children: [_jsx("div", { className: 'relative h-36 w-full cursor-crosshair rounded-ps-control', onPointerDown: (event) => {
39
39
  event.currentTarget.setPointerCapture(event.pointerId);
40
40
  pickFromArea(event);
41
41
  }, onPointerMove: (event) => {
@@ -49,7 +49,7 @@ export const PsColorPicker = ({ className, disabled, helperText, hideLabel, labe
49
49
  backgroundColor: swatchColor ? swatchColor : 'transparent',
50
50
  } }) }), _jsxs("label", { className: 'flex flex-col gap-1', children: [_jsx("span", { className: 'ps-input-helper', children: "Hue" }), _jsx("input", { className: 'ps-focus-ring h-3 w-full cursor-pointer appearance-none rounded-full', max: 360, min: 0, onChange: (event) => onChange(PsColorService.toHex({ ...hsv, hue: Number(event.target.value) })), step: 1, style: {
51
51
  background: 'linear-gradient(to right, #FF0000, #FFFF00, #00FF00, #00FFFF, #0000FF, #FF00FF, #FF0000)',
52
- }, type: 'range', value: hsv.hue })] }), _jsx("input", { "aria-label": `${label} hex`, className: 'ps-input-control ps-focus-ring h-10 w-full font-mono text-sm uppercase', maxLength: 7, onBlur: (event) => commitHex(event.target.value), onChange: (event) => setDraft(event.target.value), onKeyDown: (event) => {
52
+ }, type: 'range', value: hsv.hue })] }), _jsx("input", { "aria-label": `${label} hex`, className: 'ps-input-control ps-control-compact ps-focus-ring w-full font-mono text-sm uppercase', maxLength: 7, onBlur: (event) => commitHex(event.target.value), onChange: (event) => setDraft(event.target.value), onKeyDown: (event) => {
53
53
  if (event.key !== 'Enter')
54
54
  return;
55
55
  event.preventDefault();
@@ -6,5 +6,5 @@ import { PsComboboxInputService } from '../services/ps-combobox-input-service';
6
6
  import { PsRequiredMark } from './ps-required-mark';
7
7
  export const PsComboboxInput = ({ className, emptyText, getItemKey, getItemLabel, hideLabel = false, inputValue, isLoading = false, items, label, onInputChange, onSelectionChange, placeholder, renderItem, required, selectedKey, }) => {
8
8
  const itemsByKey = new Map(items.map((item) => [getItemKey(item), item]));
9
- return (_jsxs(ComboBox, { allowsEmptyCollection: true, "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), defaultFilter: () => true, inputValue: inputValue, items: items, onInputChange: onInputChange, selectedKey: selectedKey, onSelectionChange: (key) => onSelectionChange?.(key === null ? null : PsComboboxInputService.getItem(itemsByKey, key)), children: [label && !hideLabel ? (_jsxs(Label, { className: 'ps-input-label', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })) : null, _jsx("span", { className: hideLabel || !label ? 'relative block' : 'relative mt-2 block', children: _jsx(Input, { className: 'ps-input-control ps-focus-ring min-h-11 w-full text-sm font-semibold', placeholder: placeholder }) }), _jsx(Popover, { className: 'w-[--trigger-width] rounded-2xl border border-line bg-white/95 p-1.5 shadow-lg dark:border-white/10 dark:bg-slate-900/95', children: isLoading ? (_jsx("div", { className: 'flex items-center justify-center py-4', children: _jsx(PsSpinner, { label: 'Loading results', size: 'small' }) })) : (_jsx(ListBox, { className: 'max-h-72 overflow-y-auto outline-none', items: items, renderEmptyState: () => emptyText ? _jsx("div", { className: 'px-3 py-2 text-sm text-ink/55', children: emptyText }) : null, children: (item) => (_jsx(ListBoxItem, { className: 'ps-focus-ring cursor-pointer rounded-xl px-3 py-2 text-sm font-semibold text-ink selected:bg-primary-soft selected:text-primary hover:bg-slate-50 dark:hover:bg-white/6', id: getItemKey(item), textValue: getItemLabel(item), children: renderItem ? renderItem(item) : getItemLabel(item) })) })) })] }));
9
+ return (_jsxs(ComboBox, { allowsEmptyCollection: true, "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), defaultFilter: () => true, inputValue: inputValue, items: items, onInputChange: onInputChange, selectedKey: selectedKey, onSelectionChange: (key) => onSelectionChange?.(key === null ? null : PsComboboxInputService.getItem(itemsByKey, key)), children: [label && !hideLabel ? (_jsxs(Label, { className: 'ps-input-label', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })) : null, _jsx("span", { className: hideLabel || !label ? 'relative block' : 'relative mt-2 block', children: _jsx(Input, { className: 'ps-input-control ps-focus-ring w-full text-sm font-semibold', placeholder: placeholder }) }), _jsx(Popover, { className: 'w-[--trigger-width] rounded-2xl border border-line bg-white/95 p-1.5 shadow-lg dark:border-white/10 dark:bg-slate-900/95', children: isLoading ? (_jsx("div", { className: 'flex items-center justify-center py-4', children: _jsx(PsSpinner, { label: 'Loading results', size: 'small' }) })) : (_jsx(ListBox, { className: 'max-h-72 overflow-y-auto outline-none', items: items, renderEmptyState: () => emptyText ? _jsx("div", { className: 'px-3 py-2 text-sm text-ink/55', children: emptyText }) : null, children: (item) => (_jsx(ListBoxItem, { className: 'ps-focus-ring cursor-pointer rounded-ps-control px-3 py-2 text-sm font-semibold text-ink selected:bg-primary-soft selected:text-primary hover:bg-slate-50 dark:hover:bg-white/6', id: getItemKey(item), textValue: getItemLabel(item), children: renderItem ? renderItem(item) : getItemLabel(item) })) })) })] }));
10
10
  };
@@ -38,5 +38,5 @@ export const PsDateInput = ({ className, defaultValue, disabled, helperText, hid
38
38
  setUncontrolledValue(nextValue);
39
39
  onChange?.(nextValue);
40
40
  };
41
- return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [_jsx(DatePicker, { autoComplete: 'off', calendarClassName: PallasoftClassNameService.merge('ps-floating-panel ps-datepicker', view === PsCalendarView.day ? undefined : PsDateInputConfig.pickingClassName), className: 'ps-input-control ps-focus-ring min-h-11 w-full pr-10 text-sm font-semibold', dateFormat: [...PsDateInputConfig.inputFormats], disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onCalendarClose: () => setView(PsCalendarView.day), onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, renderCustomHeader: (headerProps) => (_jsx(PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: setView, view: view })), required: required, selected: PsDateInputService.parse(currentValue), showPopperArrow: false, wrapperClassName: 'block w-full' }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ink/50', iconKey: PsIconKey.Calendar }), name ? _jsx("input", { name: name, type: 'hidden', value: currentValue }) : null] }), helperText ? _jsx("span", { className: 'ps-input-helper', children: helperText }) : null] }));
41
+ return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [_jsx(DatePicker, { autoComplete: 'off', calendarClassName: PallasoftClassNameService.merge('ps-floating-panel ps-datepicker', view === PsCalendarView.day ? undefined : PsDateInputConfig.pickingClassName), className: 'ps-input-control ps-focus-ring w-full pr-10 text-sm font-semibold', dateFormat: [...PsDateInputConfig.inputFormats], disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onCalendarClose: () => setView(PsCalendarView.day), onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, renderCustomHeader: (headerProps) => (_jsx(PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: setView, view: view })), required: required, selected: PsDateInputService.parse(currentValue), showPopperArrow: false, wrapperClassName: 'block w-full' }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ink/50', iconKey: PsIconKey.Calendar }), name ? _jsx("input", { name: name, type: 'hidden', value: currentValue }) : null] }), helperText ? _jsx("span", { className: 'ps-input-helper', children: helperText }) : null] }));
42
42
  };
@@ -2,5 +2,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { PsDateInput } from './ps-date-input';
3
3
  import { PsFormControl } from './ps-form-control';
4
4
  export const PsDatePresetField = ({ errorText, hideLabel, label, onChange, presets, presetsDisabled = false, presetsLabel, required, value, }) => (_jsxs("div", { className: 'flex flex-col gap-2', children: [_jsx(PsFormControl, { errorText: errorText, children: _jsx(PsDateInput, { hideLabel: hideLabel, label: label, onChange: onChange, required: required, value: value }) }), _jsx("div", { "aria-label": presetsLabel, className: 'flex flex-wrap gap-1.5', role: 'group', children: presets.map((preset) => (_jsx("button", { "aria-pressed": preset.date !== '' && preset.date === value, className: preset.date !== '' && preset.date === value
5
- ? 'ps-focus-ring rounded-full bg-primary px-2.5 py-1 text-xs font-semibold text-white'
6
- : 'ps-focus-ring rounded-full border border-line px-2.5 py-1 text-xs font-medium text-ink/70 hover:border-primary/40 hover:text-ink disabled:opacity-40', disabled: presetsDisabled, onClick: () => onChange(preset.date), type: 'button', children: preset.label }, preset.label))) })] }));
5
+ ? 'ps-focus-ring rounded-ps-control bg-primary px-2.5 py-1 text-xs font-semibold text-white'
6
+ : 'ps-focus-ring rounded-ps-control border border-line px-2.5 py-1 text-xs font-medium text-ink/70 hover:border-primary/40 hover:text-ink disabled:opacity-40', disabled: presetsDisabled, onClick: () => onChange(preset.date), type: 'button', children: preset.label }, preset.label))) })] }));
@@ -1,3 +1,3 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
- export const PsFieldSkeleton = ({ className, hideLabel, label, rows = 1, }) => (_jsxs("div", { "aria-busy": 'true', className: 'block', role: 'status', children: [_jsx("span", { className: 'sr-only', children: label }), hideLabel ? null : _jsx("span", { className: 'ps-skeleton mb-2 block h-2.5 w-24 rounded-full' }), _jsx("span", { className: PallasoftClassNameService.merge('ps-skeleton block w-full rounded-ps-control', rows > 1 ? 'min-h-24' : 'min-h-11', className) })] }));
3
+ export const PsFieldSkeleton = ({ className, hideLabel, label, rows = 1, }) => (_jsxs("div", { "aria-busy": 'true', className: 'block', role: 'status', children: [_jsx("span", { className: 'sr-only', children: label }), hideLabel ? null : _jsx("span", { className: 'ps-skeleton mb-2 block h-2.5 w-24 rounded-full' }), _jsx("span", { className: PallasoftClassNameService.merge('ps-skeleton block w-full rounded-ps-control', rows > 1 ? 'min-h-24' : 'min-h-ps-control', className) })] }));
@@ -25,5 +25,5 @@ export const PsFilePicker = ({ accept, acceptLabel, className, disabled, dropLab
25
25
  }
26
26
  onFileLoad(newFile);
27
27
  };
28
- return (_jsxs("div", { className: PallasoftClassNameService.merge('relative flex h-48 w-full flex-col items-center justify-center rounded-lg border-2 border-dashed border-line p-4 transition-all hover:border-primary/50 hover:bg-primary/5 sm:h-64', className), children: [_jsxs("div", { className: 'flex flex-col items-center gap-3 text-center', children: [_jsx(PsIcon, { iconKey: 'upload', className: 'h-8 w-8 text-primary' }), _jsxs("div", { children: [_jsx("p", { className: 'text-body-2 font-medium text-ink sm:text-body-1', children: dropLabel }), _jsx("p", { className: 'mt-1 text-body-3 text-ink/60 sm:text-body-2', children: "or click to browse your files" }), maxSizeLabel ? _jsx("p", { className: 'mt-3 text-body-3 text-ink/60', children: maxSizeLabel }) : null, _jsxs("p", { className: 'text-body-3 text-ink/60', children: ["Accepted formats: ", acceptLabel] })] })] }), _jsx("input", { type: 'file', accept: acceptAttr, className: 'absolute inset-0 h-full w-full cursor-pointer opacity-0', "aria-label": 'File upload', onChange: onFileChange, disabled: disabled, "aria-disabled": disabled })] }));
28
+ return (_jsxs("div", { className: PallasoftClassNameService.merge('relative flex h-48 w-full flex-col items-center justify-center rounded-ps-control border-2 border-dashed border-line p-4 transition-all hover:border-primary/50 hover:bg-primary/5 sm:h-64', className), children: [_jsxs("div", { className: 'flex flex-col items-center gap-3 text-center', children: [_jsx(PsIcon, { iconKey: 'upload', className: 'h-8 w-8 text-primary' }), _jsxs("div", { children: [_jsx("p", { className: 'text-body-2 font-medium text-ink sm:text-body-1', children: dropLabel }), _jsx("p", { className: 'mt-1 text-body-3 text-ink/60 sm:text-body-2', children: "or click to browse your files" }), maxSizeLabel ? _jsx("p", { className: 'mt-3 text-body-3 text-ink/60', children: maxSizeLabel }) : null, _jsxs("p", { className: 'text-body-3 text-ink/60', children: ["Accepted formats: ", acceptLabel] })] })] }), _jsx("input", { type: 'file', accept: acceptAttr, className: 'absolute inset-0 h-full w-full cursor-pointer opacity-0', "aria-label": 'File upload', onChange: onFileChange, disabled: disabled, "aria-disabled": disabled })] }));
29
29
  };
@@ -20,7 +20,7 @@ export const PsMultiSelectInput = ({ className, defaultValue, disabled, helperTe
20
20
  setUncontrolledValue(nextValue);
21
21
  onChange?.(nextValue);
22
22
  };
23
- return (_jsxs(Select, { "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, selectionMode: 'multiple', value: currentValue.filter((selected) => labelByValue.has(selected)), children: [hideLabel ? null : (_jsxs(Label, { className: 'ps-input-label block', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })), _jsxs(Button, { className: PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex min-h-11 w-full items-center py-1.5 pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), children: [_jsx(SelectValue, { className: 'flex min-w-0 flex-1 flex-wrap gap-1.5', children: ({ isPlaceholder }) => isPlaceholder ? (_jsx("span", { className: 'font-medium text-ink/45', children: placeholder })) : (currentValue
23
+ return (_jsxs(Select, { "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, selectionMode: 'multiple', value: currentValue.filter((selected) => labelByValue.has(selected)), children: [hideLabel ? null : (_jsxs(Label, { className: 'ps-input-label block', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })), _jsxs(Button, { className: PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex w-full items-center py-1.5 pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), children: [_jsx(SelectValue, { className: 'flex min-w-0 flex-1 flex-wrap gap-1.5', children: ({ isPlaceholder }) => isPlaceholder ? (_jsx("span", { className: 'font-medium text-ink/45', children: placeholder })) : (currentValue
24
24
  .filter((selected) => labelByValue.has(selected))
25
- .map((selected) => (_jsx("span", { className: 'inline-flex max-w-full items-center rounded-full bg-primary/12 px-2.5 py-0.5 text-xs font-semibold text-ink', children: _jsx("span", { className: 'truncate', children: labelByValue.get(selected) }) }, selected)))) }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: PsIconKey.Chevron })] }), helperText ? (_jsx(Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, _jsx(Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsx(ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => _jsx(PsSelectOptionItem, { option: option }) }) })] }));
25
+ .map((selected) => (_jsx("span", { className: 'inline-flex max-w-full items-center rounded-ps-control bg-primary/12 px-2.5 py-0.5 text-xs font-semibold text-ink', children: _jsx("span", { className: 'truncate', children: labelByValue.get(selected) }) }, selected)))) }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: PsIconKey.Chevron })] }), helperText ? (_jsx(Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, _jsx(Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsx(ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => _jsx(PsSelectOptionItem, { option: option }) }) })] }));
26
26
  };
@@ -34,7 +34,7 @@ export const PsPhoneInput = ({ className, defaultCountry = PsPhoneInputConfig.de
34
34
  emit(national, code);
35
35
  document.getElementById(inputId)?.focus();
36
36
  };
37
- return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: PallasoftClassNameService.merge('ps-input-control flex min-h-11 items-stretch overflow-hidden p-0 focus-within:border-primary', hideLabel ? '' : 'mt-2', isInvalid ? 'border-danger bg-danger/5' : '', disabled ? 'opacity-60' : ''), children: [_jsxs(DialogTrigger, { isOpen: isOpen, onOpenChange: setIsOpen, children: [_jsxs(Button, { "aria-label": PsPhoneInputConfig.countryLabel, className: 'ps-focus-ring flex shrink-0 items-center gap-1.5 border-r border-line px-3 text-sm font-semibold text-ink', isDisabled: disabled, children: [country, _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-3.5 w-3.5 text-ink/45', iconKey: PsIconKey.Chevron })] }), _jsx(Popover, { className: 'ps-floating-panel w-72 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsxs(Dialog, { "aria-label": PsPhoneInputConfig.countryLabel, className: 'flex flex-col outline-none', children: [_jsx("div", { className: 'border-b border-line p-2', children: _jsx("input", { "aria-label": PsPhoneInputConfig.searchPlaceholder, autoFocus: true, className: 'ps-input-control ps-focus-ring h-10 w-full text-sm', onChange: (event) => setQuery(event.target.value), placeholder: PsPhoneInputConfig.searchPlaceholder, type: 'search', value: query }) }), _jsx("ul", { className: 'ps-scrollbar-hidden max-h-64 overflow-y-auto p-1.5', role: 'listbox', children: matches.length === 0 ? (_jsx("li", { className: 'px-3 py-2.5 text-sm text-ink/50', children: PsPhoneInputConfig.emptyMessage })) : (matches.map((option) => (_jsx("li", { role: 'none', children: _jsxs("button", { "aria-selected": option.code === country, className: PallasoftClassNameService.merge('ps-focus-ring flex w-full items-center justify-between gap-3 rounded-ps-control px-3 py-2.5 text-left text-sm', option.code === country
37
+ return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: PallasoftClassNameService.merge('ps-input-control flex items-stretch overflow-hidden p-0 focus-within:border-primary has-[:focus-visible]:outline has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-primary', hideLabel ? '' : 'mt-2', isInvalid ? 'border-danger bg-danger/5' : '', disabled ? 'opacity-60' : ''), children: [_jsxs(DialogTrigger, { isOpen: isOpen, onOpenChange: setIsOpen, children: [_jsxs(Button, { "aria-label": PsPhoneInputConfig.countryLabel, className: 'flex shrink-0 items-center gap-1.5 border-r border-line px-3 outline-none focus-visible:bg-primary/10 text-sm font-semibold text-ink', isDisabled: disabled, children: [country, _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-3.5 w-3.5 text-ink/45', iconKey: PsIconKey.Chevron })] }), _jsx(Popover, { className: 'ps-floating-panel w-72 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsxs(Dialog, { "aria-label": PsPhoneInputConfig.countryLabel, className: 'flex flex-col outline-none', children: [_jsx("div", { className: 'border-b border-line p-2', children: _jsx("input", { "aria-label": PsPhoneInputConfig.searchPlaceholder, autoFocus: true, className: 'ps-input-control ps-control-compact ps-focus-ring w-full text-sm', onChange: (event) => setQuery(event.target.value), placeholder: PsPhoneInputConfig.searchPlaceholder, type: 'search', value: query }) }), _jsx("ul", { className: 'ps-scrollbar-hidden max-h-64 overflow-y-auto p-1.5', role: 'listbox', children: matches.length === 0 ? (_jsx("li", { className: 'px-3 py-2.5 text-sm text-ink/50', children: PsPhoneInputConfig.emptyMessage })) : (matches.map((option) => (_jsx("li", { role: 'none', children: _jsxs("button", { "aria-selected": option.code === country, className: PallasoftClassNameService.merge('ps-focus-ring flex w-full items-center justify-between gap-3 rounded-ps-control px-3 py-2.5 text-left text-sm', option.code === country
38
38
  ? 'bg-primary/10 text-ink'
39
39
  : 'text-ink/80 hover:bg-mist/60 hover:text-ink'), onClick: () => choose(option.code), role: 'option', type: 'button', children: [_jsx("span", { className: 'min-w-0 truncate', children: PsPhoneInputService.highlight(option.label, query).map((part, index) => part.isMatch ? (_jsx("strong", { className: 'font-semibold text-ink', children: part.text }, index)) : (_jsx("span", { children: part.text }, index))) }), _jsxs("span", { className: 'shrink-0 text-xs text-ink/50', children: ["+", option.callingCode] })] }) }, option.code)))) })] }) })] }), _jsxs("span", { "aria-hidden": 'true', className: 'flex items-center pl-3 text-sm text-ink/45', children: [PsPhoneInputConfig.plus, PsPhoneInputService.callingCode(country)] }), _jsx("input", { "aria-invalid": isInvalid, autoComplete: 'tel-national', className: 'min-w-0 flex-1 bg-transparent px-2 text-sm text-ink outline-none', disabled: disabled, id: inputId, inputMode: 'tel', name: name, onBlur: () => {
40
40
  setIsTouched(true);
@@ -1,9 +1,8 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
3
  import { PsPortableTextEditorConfig } from '../constants/ps-portable-text-editor-config';
4
- import { PsPortableTextEditorRenderers } from '../constants/ps-portable-text-editor-renderers';
5
4
  import { PsPortableTextCore } from '../portable-text-core/components/ps-portable-text-core';
6
5
  import { PsPortableTextCoreConfig } from '../portable-text-core/constants/ps-portable-text-core-config';
7
6
  import { PsPortableTextEditorService } from '../portable-text-core/services/ps-portable-text-editor-service';
8
7
  import { PsPortableTextToolbar } from './ps-portable-text-toolbar';
9
- export const PsPortableTextEditor = ({ className, disabled = false, labels = PsPortableTextCoreConfig.labels, minRows = 4, onChange, placeholder, value, }) => (_jsx(PsPortableTextCore, { ...PsPortableTextEditorRenderers, className: PallasoftClassNameService.merge(PsPortableTextEditorConfig.classNames.root, className), disabled: disabled, editableClassName: PsPortableTextEditorConfig.classNames.editable, fallback: _jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": 'true', className: PsPortableTextEditorConfig.classNames.toolbar, children: _jsx("span", { className: 'h-9' }) }), _jsx("div", { "aria-hidden": 'true', className: PsPortableTextEditorConfig.classNames.editable, style: { minHeight: PsPortableTextEditorService.minHeight(minRows) } })] }), minRows: minRows, onChange: onChange, renderPlaceholder: () => _jsx("span", { className: 'text-ink/45', children: placeholder }), toolbar: _jsx(PsPortableTextToolbar, { disabled: disabled, labels: labels }), value: value }));
8
+ export const PsPortableTextEditor = ({ className, disabled = false, labels = PsPortableTextCoreConfig.labels, minRows = 4, onChange, placeholder, value, }) => (_jsx(PsPortableTextCore, { className: PallasoftClassNameService.merge(PsPortableTextEditorConfig.classNames.root, className), classNames: PsPortableTextEditorConfig.contentClassNames, disabled: disabled, editableClassName: PsPortableTextEditorConfig.classNames.editable, fallback: _jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": 'true', className: PsPortableTextEditorConfig.classNames.toolbar, children: _jsx("span", { className: 'h-9' }) }), _jsx("div", { "aria-hidden": 'true', className: PsPortableTextEditorConfig.classNames.editable, style: { minHeight: PsPortableTextEditorService.minHeight(minRows) } })] }), label: labels.editor, minRows: minRows, onChange: onChange, placeholder: placeholder, toolbar: _jsx(PsPortableTextToolbar, { disabled: disabled, labels: labels }), value: value }));
@@ -3,7 +3,7 @@ import { PsFormModal } from '@pallasoft/ps-popovers';
3
3
  import { PsPortableTextCoreConfig } from '../portable-text-core/constants/ps-portable-text-core-config';
4
4
  import { usePsPortableTextLinkForm } from '../portable-text-core/hooks/use-ps-portable-text-link-form';
5
5
  import { PsUrlInput } from './ps-url-input';
6
- export const PsPortableTextLinkDialog = ({ isOpen, labels, onClose, onSubmit, }) => {
7
- const form = usePsPortableTextLinkForm({ onClose, onSubmit });
6
+ export const PsPortableTextLinkDialog = ({ href, isOpen, labels, onClose, onSubmit, }) => {
7
+ const form = usePsPortableTextLinkForm({ href, isOpen, onClose, onSubmit });
8
8
  return (_jsx(PsFormModal, { cancelLabel: labels.cancel, isOpen: isOpen, isSubmitDisabled: form.isSubmitDisabled, onClose: form.close, onSubmit: form.submit, size: 'sm', submitLabel: labels.saveLink, title: labels.linkDialogTitle, children: _jsx(PsUrlInput, { "aria-invalid": form.hasError, autoFocus: true, helperText: form.hasError ? labels.invalidLink : undefined, label: labels.linkUrl, name: PsPortableTextCoreConfig.linkAnnotation, onChange: (event) => form.setAddress(event.target.value), value: form.address }) }));
9
9
  };
@@ -1,5 +1,4 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from 'react';
3
2
  import { PsPortableTextEditorConfig } from '../constants/ps-portable-text-editor-config';
4
3
  import { PsPortableTextCoreConfig } from '../portable-text-core/constants/ps-portable-text-core-config';
5
4
  import { usePsPortableTextToolbar } from '../portable-text-core/hooks/use-ps-portable-text-toolbar';
@@ -7,12 +6,8 @@ import { PsPortableTextLinkDialog } from './ps-portable-text-link-dialog';
7
6
  import { PsPortableTextToolbarButton } from './ps-portable-text-toolbar-button';
8
7
  export const PsPortableTextToolbar = ({ disabled, labels }) => {
9
8
  const toolbar = usePsPortableTextToolbar();
10
- const [isLinkOpen, setIsLinkOpen] = useState(false);
11
- return (_jsxs("div", { "aria-label": labels.toolbar, className: PsPortableTextEditorConfig.classNames.toolbar, role: 'toolbar', children: [_jsx(PsPortableTextToolbarButton, { className: 'font-bold', disabled: disabled, isActive: toolbar.active.bold, label: labels.bold, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.bold), children: "B" }), _jsx(PsPortableTextToolbarButton, { className: 'italic', disabled: disabled, isActive: toolbar.active.italic, label: labels.italic, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.italic), children: "I" }), _jsx(PsPortableTextToolbarButton, { className: 'underline', disabled: disabled, isActive: toolbar.active.underline, label: labels.underline, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.underline), children: "U" }), _jsx(PsPortableTextToolbarButton, { className: 'font-mono', disabled: disabled, isActive: toolbar.active.code, label: labels.code, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.code), children: '</>' }), _jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.link, label: toolbar.active.link ? labels.removeLink : labels.link, onClick: () => (toolbar.active.link ? toolbar.removeLink() : setIsLinkOpen(true)), children: _jsx("span", { className: 'underline', children: labels.link }) }), _jsx(PsPortableTextLinkDialog, { isOpen: isLinkOpen, labels: labels, onClose: () => {
12
- setIsLinkOpen(false);
13
- toolbar.focus();
14
- }, onSubmit: (href) => {
9
+ return (_jsxs("div", { "aria-label": labels.toolbar, className: PsPortableTextEditorConfig.classNames.toolbar, role: 'toolbar', children: [_jsx(PsPortableTextToolbarButton, { className: 'font-bold', disabled: disabled, isActive: toolbar.active.bold, label: labels.bold, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.bold), children: "B" }), _jsx(PsPortableTextToolbarButton, { className: 'italic', disabled: disabled, isActive: toolbar.active.italic, label: labels.italic, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.italic), children: "I" }), _jsx(PsPortableTextToolbarButton, { className: 'underline', disabled: disabled, isActive: toolbar.active.underline, label: labels.underline, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.underline), children: "U" }), _jsx(PsPortableTextToolbarButton, { className: 'font-mono', disabled: disabled, isActive: toolbar.active.code, label: labels.code, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.code), children: '</>' }), _jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.link, label: toolbar.active.link ? labels.removeLink : labels.link, onClick: () => (toolbar.active.link ? toolbar.removeLink() : toolbar.openLink()), children: _jsx("span", { className: 'underline', children: labels.link }) }), _jsx(PsPortableTextLinkDialog, { href: toolbar.linkHref, isOpen: toolbar.isLinkOpen, labels: labels, onClose: toolbar.closeLink, onSubmit: (href) => {
10
+ toolbar.closeLink();
15
11
  toolbar.addLink(href);
16
- setIsLinkOpen(false);
17
12
  } }), _jsx("span", { "aria-hidden": 'true', className: PsPortableTextEditorConfig.classNames.separator }), _jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.bulletedList, label: labels.bulletedList, onClick: () => toolbar.toggleListItem(PsPortableTextCoreConfig.listItems.bullet), children: "\u2022" }), _jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.numberedList, label: labels.numberedList, onClick: () => toolbar.toggleListItem(PsPortableTextCoreConfig.listItems.number), children: "1." }), _jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.quote, label: labels.quote, onClick: toolbar.toggleQuote, children: "\u201D" })] }));
18
13
  };
@@ -21,5 +21,5 @@ export const PsSelectInput = ({ className, defaultValue, disabled, helperText, h
21
21
  setUncontrolledValue(nextValue);
22
22
  onChange?.(nextValue);
23
23
  };
24
- return (_jsxs(Select, { "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, value: hasOption ? currentValue : null, children: [hideLabel ? null : (_jsxs(Label, { className: 'ps-input-label block', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })), _jsxs(Button, { className: PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex min-h-11 w-full items-center pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), children: [_jsx(SelectValue, { className: 'min-w-0 flex-1 truncate', children: ({ isPlaceholder, selectedText }) => isPlaceholder ? (_jsx("span", { className: 'font-medium text-ink/45', children: placeholder })) : (selectedText) }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: PsIconKey.Chevron })] }), helperText ? (_jsx(Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, _jsx(Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsx(ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => _jsx(PsSelectOptionItem, { option: option }) }) })] }));
24
+ return (_jsxs(Select, { "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, value: hasOption ? currentValue : null, children: [hideLabel ? null : (_jsxs(Label, { className: 'ps-input-label block', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })), _jsxs(Button, { className: PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex w-full items-center pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), children: [_jsx(SelectValue, { className: 'min-w-0 flex-1 truncate', children: ({ isPlaceholder, selectedText }) => isPlaceholder ? (_jsx("span", { className: 'font-medium text-ink/45', children: placeholder })) : (selectedText) }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: PsIconKey.Chevron })] }), helperText ? (_jsx(Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, _jsx(Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsx(ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => _jsx(PsSelectOptionItem, { option: option }) }) })] }));
25
25
  };
@@ -1,3 +1,3 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
- export const PsToggle = ({ description, isChecked, label, name, onChange }) => (_jsxs("label", { className: 'ps-focus-ring flex cursor-pointer items-center justify-between gap-4 rounded-2xl border border-line bg-white/78 px-4 py-3 text-ink transition-colors hover:border-primary/35 dark:border-white/10 dark:bg-white/6 dark:text-white', children: [_jsxs("span", { children: [_jsx("span", { className: 'block text-sm font-semibold text-current', children: label }), description ? (_jsx("span", { className: 'mt-1 block text-xs leading-5 text-slate-500 dark:text-slate-400', children: description })) : null] }), _jsx("input", { checked: isChecked, className: 'sr-only', name: name, onChange: (event) => onChange?.(event.target.checked), type: 'checkbox' }), _jsx("span", { className: PallasoftClassNameService.merge('flex h-7 w-12 items-center rounded-full p-1 transition', isChecked ? 'bg-primary' : 'bg-slate-200 dark:bg-slate-700'), children: _jsx("span", { className: PallasoftClassNameService.merge('h-5 w-5 rounded-full bg-white ring-1 ring-black/5 transition dark:ring-white/10', isChecked && 'translate-x-5') }) })] }));
3
+ export const PsToggle = ({ description, isChecked, label, name, onChange }) => (_jsxs("label", { className: 'ps-control flex cursor-pointer items-center justify-between gap-4 rounded-ps-control border border-line bg-white/78 px-4 py-3 has-[:focus-visible]:outline has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-primary text-ink transition-colors hover:border-primary/35 dark:border-white/10 dark:bg-white/6 dark:text-white', children: [_jsxs("span", { children: [_jsx("span", { className: 'block text-sm font-semibold text-current', children: label }), description ? (_jsx("span", { className: 'mt-1 block text-xs leading-5 text-slate-500 dark:text-slate-400', children: description })) : null] }), _jsx("input", { checked: isChecked, className: 'sr-only', name: name, onChange: (event) => onChange?.(event.target.checked), type: 'checkbox' }), _jsx("span", { className: PallasoftClassNameService.merge('flex h-7 w-12 items-center rounded-full p-1 transition', isChecked ? 'bg-primary' : 'bg-slate-200 dark:bg-slate-700'), children: _jsx("span", { className: PallasoftClassNameService.merge('h-5 w-5 rounded-full bg-white ring-1 ring-black/5 transition dark:ring-white/10', isChecked && 'translate-x-5') }) })] }));
@@ -40,7 +40,7 @@ export const PsYearInput = ({ className, defaultValue, disabled, helperText, hid
40
40
  setUncontrolledValue(nextValue);
41
41
  onChange?.(nextValue);
42
42
  };
43
- return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [_jsx(DatePicker, { autoComplete: 'off', calendarClassName: `ps-floating-panel ps-datepicker ${PsDateInputConfig.pickingClassName}`, className: 'ps-input-control ps-focus-ring min-h-11 w-full pr-10 text-sm font-semibold', dateFormat: PsYearInputConfig.format, disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, ref: pickerRef, renderCustomHeader: (headerProps) => (_jsx(PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: () => undefined, onYearPick: (year) => {
43
+ return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [_jsx(DatePicker, { autoComplete: 'off', calendarClassName: `ps-floating-panel ps-datepicker ${PsDateInputConfig.pickingClassName}`, className: 'ps-input-control ps-focus-ring w-full pr-10 text-sm font-semibold', dateFormat: PsYearInputConfig.format, disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, ref: pickerRef, renderCustomHeader: (headerProps) => (_jsx(PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: () => undefined, onYearPick: (year) => {
44
44
  handleChange(PsYearInputService.startOfYear(year));
45
45
  pickerRef.current?.setOpen(false);
46
46
  }, selectedYear: selected === null ? undefined : selected.getFullYear(), view: PsCalendarView.year })), required: required, selected: selected, showPopperArrow: false, wrapperClassName: 'block w-full' }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute top-1/2 right-3 h-4 w-4 -translate-y-1/2 text-ink/50', iconKey: PsIconKey.Calendar }), name ? _jsx("input", { name: name, type: 'hidden', value: currentValue }) : null] }), helperText ? _jsx("span", { className: 'ps-input-helper', children: helperText }) : null] }));
@@ -0,0 +1,6 @@
1
+ export const PsCalendarHeaderClasses = {
2
+ navigationButton: 'ps-focus-ring ps-control-square ps-control-compact flex items-center justify-center rounded-ps-control text-ink/60 transition-colors hover:bg-primary/10 hover:text-ink disabled:cursor-not-allowed disabled:opacity-30',
3
+ titleButton: 'ps-focus-ring ps-control-compact ps-control-padding-compact flex items-center gap-1 rounded-ps-control text-sm font-semibold text-ink transition-colors hover:bg-primary/10',
4
+ cell: 'ps-focus-ring ps-control flex items-center justify-center rounded-ps-control text-sm font-medium text-ink transition-colors hover:bg-primary/10 disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent',
5
+ selectedCell: 'bg-primary font-bold text-[var(--ps-color-primary-contrast)] hover:bg-primary',
6
+ };
@@ -2,9 +2,17 @@ export const PsPortableTextEditorConfig = {
2
2
  classNames: {
3
3
  editable: 'ps-input-control w-full resize-none overflow-y-auto rounded-t-none border-t-0 leading-6 outline-none',
4
4
  root: 'block',
5
- toolbar: 'flex flex-wrap items-center gap-1 rounded-t-xl border border-line bg-white p-1 dark:bg-transparent',
6
- button: 'ps-focus-ring inline-flex h-9 min-w-9 items-center justify-center rounded-lg px-2 text-sm text-ink/70 transition-colors hover:bg-ink/5 hover:text-ink disabled:cursor-not-allowed disabled:opacity-40',
5
+ toolbar: 'flex flex-wrap items-center gap-1 rounded-t-ps-control border border-line bg-white p-1 dark:bg-transparent',
6
+ button: 'ps-focus-ring ps-control-compact inline-flex min-w-ps-control-compact items-center justify-center rounded-ps-control px-2 text-sm text-ink/70 transition-colors hover:bg-ink/5 hover:text-ink disabled:cursor-not-allowed disabled:opacity-40',
7
7
  buttonActive: 'bg-primary text-white hover:bg-primary hover:text-white',
8
8
  separator: 'mx-1 h-5 w-px bg-line',
9
9
  },
10
+ contentClassNames: {
11
+ blockquote: 'border-l-2 border-primary pl-3 text-ink/80',
12
+ bulletList: 'list-disc pl-6',
13
+ code: 'rounded bg-ink/10 px-1 font-mono text-[0.9em]',
14
+ link: 'text-primary underline',
15
+ orderedList: 'list-decimal pl-6',
16
+ placeholder: 'before:pointer-events-none before:float-left before:h-0 before:text-ink/45 before:content-[attr(data-placeholder)]',
17
+ },
10
18
  };
package/dist/esm/index.js CHANGED
@@ -47,3 +47,10 @@ export * from './constants/ps-select-with-create-config';
47
47
  export * from './interfaces/ps-date-preset-data';
48
48
  export * from './components/ps-option-card-group';
49
49
  export * from './interfaces/ps-option-card-data';
50
+ export * from './components/ps-checkbox-matrix';
51
+ export * from './interfaces/ps-checkbox-matrix-cell';
52
+ export * from './interfaces/ps-checkbox-matrix-column';
53
+ export * from './interfaces/ps-checkbox-matrix-group';
54
+ export * from './interfaces/ps-checkbox-matrix-labels';
55
+ export * from './interfaces/ps-checkbox-matrix-row';
56
+ export * from './services/ps-checkbox-matrix-service';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export const PsPortableTextCoreEditor = ({ className, fallback }) => (_jsx("div", { className: className, children: fallback }));
@@ -0,0 +1,64 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from 'react';
3
+ import { EditorContent, useEditor, useEditorState } from '@tiptap/react';
4
+ import { PsPortableTextCoreContext } from '../contexts/ps-portable-text-core-context';
5
+ import { PsPortableTextCommandService } from '../services/ps-portable-text-command-service';
6
+ import { PsPortableTextConverterService } from '../services/ps-portable-text-converter-service';
7
+ import { PsPortableTextEditorService } from '../services/ps-portable-text-editor-service';
8
+ import { PsPortableTextExtensionService } from '../services/ps-portable-text-extension-service';
9
+ export const PsPortableTextCoreEditor = ({ className, classNames, disabled = false, editableClassName = '', label, minRows = 4, onChange, placeholder = '', toolbar, value, }) => {
10
+ const [isLinkOpen, setIsLinkOpen] = useState(false);
11
+ const lastValue = useRef(value);
12
+ const editor = useEditor({
13
+ content: PsPortableTextConverterService.toDocument(value),
14
+ editable: !disabled,
15
+ editorProps: {
16
+ attributes: {
17
+ ...(label === undefined ? {} : { 'aria-label': label }),
18
+ 'aria-multiline': 'true',
19
+ 'class': editableClassName,
20
+ 'role': 'textbox',
21
+ 'style': `min-height: ${PsPortableTextEditorService.minHeight(minRows)}`,
22
+ },
23
+ },
24
+ extensions: PsPortableTextExtensionService.extensions({
25
+ classNames,
26
+ onLinkShortcut: () => setIsLinkOpen(true),
27
+ placeholder,
28
+ }),
29
+ immediatelyRender: true,
30
+ }, []);
31
+ const state = useEditorState({
32
+ editor,
33
+ selector: ({ editor: current }) => PsPortableTextCommandService.state(current),
34
+ });
35
+ useEffect(() => {
36
+ editor.setEditable(!disabled, false);
37
+ }, [editor, disabled]);
38
+ useEffect(() => {
39
+ const update = () => {
40
+ const next = PsPortableTextConverterService.toBlocks(editor.getJSON());
41
+ lastValue.current = next;
42
+ onChange(next);
43
+ };
44
+ editor.on('update', update);
45
+ return () => {
46
+ editor.off('update', update);
47
+ };
48
+ }, [editor, onChange]);
49
+ useEffect(() => {
50
+ if (PsPortableTextEditorService.isSame(value, lastValue.current))
51
+ return;
52
+ lastValue.current = value;
53
+ editor.commands.setContent(PsPortableTextConverterService.toDocument(value), {
54
+ emitUpdate: false,
55
+ });
56
+ }, [editor, value]);
57
+ return (_jsx("div", { className: className, children: _jsxs(PsPortableTextCoreContext.Provider, { value: {
58
+ closeLink: () => setIsLinkOpen(false),
59
+ editor,
60
+ isLinkOpen,
61
+ openLink: () => setIsLinkOpen(true),
62
+ state,
63
+ }, children: [toolbar, _jsx(EditorContent, { editor: editor })] }) }));
64
+ };
@@ -1,31 +1,10 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useRef, useState } from 'react';
3
- import { EditorProvider, PortableTextEditable, } from '@portabletext/editor';
4
- import { EventListenerPlugin } from '@portabletext/editor/plugins';
5
- import { PsPortableTextCoreConfig } from '../constants/ps-portable-text-core-config';
6
- import { PsPortableTextEditorService } from '../services/ps-portable-text-editor-service';
7
- export const PsPortableTextCore = ({ className, disabled = false, editableClassName, fallback, minRows = 4, onChange, renderAnnotation, renderBlock, renderDecorator, renderPlaceholder, toolbar, value, }) => {
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { PsPortableTextCoreEditor } from '@pallasoft/ps-input-components/portable-text-engine';
4
+ export const PsPortableTextCore = (props) => {
8
5
  const [isMounted, setIsMounted] = useState(false);
9
- const [version, setVersion] = useState(0);
10
- const lastValue = useRef(value);
11
6
  useEffect(() => {
12
7
  setIsMounted(true);
13
8
  }, []);
14
- useEffect(() => {
15
- if (PsPortableTextEditorService.isSame(value, lastValue.current))
16
- return;
17
- lastValue.current = value;
18
- setVersion((current) => current + 1);
19
- }, [value]);
20
- return (_jsx("div", { className: className, children: isMounted ? (_jsxs(EditorProvider, { initialConfig: {
21
- initialValue: value,
22
- readOnly: disabled,
23
- schemaDefinition: PsPortableTextCoreConfig.schemaDefinition,
24
- }, children: [_jsx(EventListenerPlugin, { on: (event) => {
25
- if (event.type !== 'mutation')
26
- return;
27
- const next = Array.isArray(event.value) ? event.value : [];
28
- lastValue.current = next;
29
- onChange(next);
30
- } }), toolbar, _jsx(PortableTextEditable, { className: editableClassName, readOnly: disabled, renderAnnotation: renderAnnotation, renderBlock: renderBlock, renderDecorator: renderDecorator, renderPlaceholder: renderPlaceholder, style: { minHeight: PsPortableTextEditorService.minHeight(minRows) } })] }, version)) : (fallback) }));
9
+ return isMounted ? (_jsx(PsPortableTextCoreEditor, { ...props })) : (_jsx("div", { className: props.className, children: props.fallback }));
31
10
  };
@@ -1,11 +1,13 @@
1
1
  import { Common } from '@pallasoft/ps-models';
2
- import { defineSchema } from '@portabletext/editor';
3
2
  const Models = Common.PortableTextConfig;
4
3
  export const PsPortableTextCoreConfig = {
5
4
  linkAnnotation: Models.linkType,
6
5
  mailtoPrefix: 'mailto:',
7
6
  emailPattern: /^[^\s@/:]+@[^\s@/:]+\.[^\s@/:]+$/,
8
7
  lineHeightRem: 1.5,
8
+ lineBreak: '\n',
9
+ defaultLinkProtocol: 'https',
10
+ keyPrefix: { block: 'b', link: 'l', span: 's' },
9
11
  decorators: {
10
12
  bold: Models.decorators[0],
11
13
  code: Models.decorators[3],
@@ -14,19 +16,37 @@ export const PsPortableTextCoreConfig = {
14
16
  },
15
17
  styles: { blockquote: Models.styles[1], normal: Models.styles[0] },
16
18
  listItems: { bullet: Models.listItems[0], number: Models.listItems[1] },
17
- schemaDefinition: defineSchema({
18
- annotations: [{ name: Models.linkType, fields: [{ name: 'href', type: 'string' }] }],
19
- blockObjects: [],
20
- decorators: Models.decorators.map((name) => ({ name })),
21
- inlineObjects: [],
22
- lists: Models.listItems.map((name) => ({ name })),
23
- styles: Models.styles.map((name) => ({ name })),
24
- }),
19
+ decoratorMarks: {
20
+ [Models.decorators[0]]: 'bold',
21
+ [Models.decorators[1]]: 'italic',
22
+ [Models.decorators[2]]: 'underline',
23
+ [Models.decorators[3]]: 'code',
24
+ },
25
+ listNodes: {
26
+ [Models.listItems[0]]: 'bulletList',
27
+ [Models.listItems[1]]: 'orderedList',
28
+ },
29
+ nodes: {
30
+ blockquote: 'blockquote',
31
+ bulletList: 'bulletList',
32
+ document: 'doc',
33
+ hardBreak: 'hardBreak',
34
+ listItem: 'listItem',
35
+ orderedList: 'orderedList',
36
+ paragraph: 'paragraph',
37
+ text: 'text',
38
+ },
39
+ linkMark: 'link',
40
+ linkShortcutExtension: 'psLinkShortcut',
41
+ listItemContent: 'paragraph (bulletList | orderedList)*',
42
+ blockquoteContent: 'paragraph+',
43
+ shortcuts: { link: 'Mod-k', nest: 'Tab', unnest: 'Shift-Tab' },
25
44
  labels: {
26
45
  bold: 'Bold',
27
46
  bulletedList: 'Bulleted list',
28
47
  cancel: 'Cancel',
29
48
  code: 'Code',
49
+ editor: 'Text',
30
50
  invalidLink: 'Enter a web address or email address',
31
51
  italic: 'Italic',
32
52
  link: 'Link',
@@ -0,0 +1,9 @@
1
+ import { createContext } from 'react';
2
+ import { PsPortableTextCommandService } from '../services/ps-portable-text-command-service';
3
+ export const PsPortableTextCoreContext = createContext({
4
+ closeLink: () => undefined,
5
+ editor: null,
6
+ isLinkOpen: false,
7
+ openLink: () => undefined,
8
+ state: PsPortableTextCommandService.state(null),
9
+ });
@@ -1,8 +1,14 @@
1
- import { useState } from 'react';
1
+ import { useEffect, useState } from 'react';
2
2
  import { PsPortableTextEditorService } from '../services/ps-portable-text-editor-service';
3
- export const usePsPortableTextLinkForm = ({ onClose, onSubmit, }) => {
3
+ export const usePsPortableTextLinkForm = ({ href, isOpen = false, onClose, onSubmit, }) => {
4
4
  const [address, setAddress] = useState('');
5
5
  const [hasError, setHasError] = useState(false);
6
+ useEffect(() => {
7
+ if (!isOpen)
8
+ return;
9
+ setAddress(href === undefined ? '' : href);
10
+ setHasError(false);
11
+ }, [isOpen]);
6
12
  return {
7
13
  address,
8
14
  close: () => {
@@ -19,14 +25,14 @@ export const usePsPortableTextLinkForm = ({ onClose, onSubmit, }) => {
19
25
  submit: (event) => {
20
26
  event.preventDefault();
21
27
  event.stopPropagation();
22
- const href = PsPortableTextEditorService.normalizeLink(address);
23
- if (href === null) {
28
+ const normalized = PsPortableTextEditorService.normalizeLink(address);
29
+ if (normalized === null) {
24
30
  setHasError(true);
25
31
  return;
26
32
  }
27
33
  setAddress('');
28
34
  setHasError(false);
29
- onSubmit(href);
35
+ onSubmit(normalized);
30
36
  },
31
37
  };
32
38
  };
@@ -1,54 +1,22 @@
1
- import { useEditor, useEditorSelector } from '@portabletext/editor';
2
- import { isActiveAnnotation, isActiveDecorator, isActiveListItem, isActiveStyle, } from '@portabletext/editor/selectors';
3
- import { PsPortableTextCoreConfig } from '../constants/ps-portable-text-core-config';
1
+ import { useContext } from 'react';
2
+ import { PsPortableTextCoreContext } from '../contexts/ps-portable-text-core-context';
3
+ import { PsPortableTextCommandService } from '../services/ps-portable-text-command-service';
4
4
  export const usePsPortableTextToolbar = () => {
5
- const editor = useEditor();
6
- const isBold = useEditorSelector(editor, isActiveDecorator(PsPortableTextCoreConfig.decorators.bold));
7
- const isItalic = useEditorSelector(editor, isActiveDecorator(PsPortableTextCoreConfig.decorators.italic));
8
- const isUnderline = useEditorSelector(editor, isActiveDecorator(PsPortableTextCoreConfig.decorators.underline));
9
- const isCode = useEditorSelector(editor, isActiveDecorator(PsPortableTextCoreConfig.decorators.code));
10
- const isBulletedList = useEditorSelector(editor, isActiveListItem(PsPortableTextCoreConfig.listItems.bullet));
11
- const isNumberedList = useEditorSelector(editor, isActiveListItem(PsPortableTextCoreConfig.listItems.number));
12
- const isQuote = useEditorSelector(editor, isActiveStyle(PsPortableTextCoreConfig.styles.blockquote));
13
- const isLink = useEditorSelector(editor, isActiveAnnotation(PsPortableTextCoreConfig.linkAnnotation));
14
- const focus = () => editor.send({ type: 'focus' });
5
+ const { closeLink, editor, isLinkOpen, openLink, state } = useContext(PsPortableTextCoreContext);
15
6
  return {
16
- active: {
17
- bold: isBold,
18
- bulletedList: isBulletedList,
19
- code: isCode,
20
- italic: isItalic,
21
- link: isLink,
22
- numberedList: isNumberedList,
23
- quote: isQuote,
24
- underline: isUnderline,
25
- },
26
- addLink: (href) => {
27
- editor.send({
28
- type: 'annotation.add',
29
- annotation: { name: PsPortableTextCoreConfig.linkAnnotation, value: { href } },
30
- });
31
- focus();
32
- },
33
- focus,
34
- removeLink: () => {
35
- editor.send({
36
- type: 'annotation.remove',
37
- annotation: { name: PsPortableTextCoreConfig.linkAnnotation },
38
- });
39
- focus();
40
- },
41
- toggleDecorator: (decorator) => {
42
- editor.send({ type: 'decorator.toggle', decorator });
43
- focus();
44
- },
45
- toggleListItem: (listItem) => {
46
- editor.send({ type: 'list item.toggle', listItem });
47
- focus();
48
- },
49
- toggleQuote: () => {
50
- editor.send({ type: 'style.toggle', style: PsPortableTextCoreConfig.styles.blockquote });
51
- focus();
7
+ active: state.active,
8
+ addLink: (href) => PsPortableTextCommandService.setLink(editor, href),
9
+ closeLink: () => {
10
+ closeLink();
11
+ PsPortableTextCommandService.focus(editor);
52
12
  },
13
+ focus: () => PsPortableTextCommandService.focus(editor),
14
+ isLinkOpen,
15
+ linkHref: state.linkHref,
16
+ openLink,
17
+ removeLink: () => PsPortableTextCommandService.removeLink(editor),
18
+ toggleDecorator: (decorator) => PsPortableTextCommandService.toggleDecorator(editor, decorator),
19
+ toggleListItem: (listItem) => PsPortableTextCommandService.toggleListItem(editor, listItem),
20
+ toggleQuote: () => PsPortableTextCommandService.toggleQuote(editor),
53
21
  };
54
22
  };
@@ -2,5 +2,9 @@ export * from './components/ps-portable-text-core';
2
2
  export * from './constants/ps-portable-text-core-config';
3
3
  export * from './hooks/use-ps-portable-text-link-form';
4
4
  export * from './hooks/use-ps-portable-text-toolbar';
5
+ export * from './interfaces/ps-portable-text-active-formats';
6
+ export * from './interfaces/ps-portable-text-core-class-names';
7
+ export * from './interfaces/ps-portable-text-core-props';
5
8
  export * from './interfaces/ps-portable-text-editor-labels';
9
+ export * from './services/ps-portable-text-converter-service';
6
10
  export * from './services/ps-portable-text-editor-service';