@wordpress/components 25.9.1 → 25.11.1-next.f8d8eceb.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.
- package/CHANGELOG.md +48 -0
- package/build/alignment-matrix-control/cell.js +8 -5
- package/build/alignment-matrix-control/cell.js.map +1 -1
- package/build/alignment-matrix-control/index.js +27 -43
- package/build/alignment-matrix-control/index.js.map +1 -1
- package/build/alignment-matrix-control/utils.js +29 -9
- package/build/alignment-matrix-control/utils.js.map +1 -1
- package/build/autocomplete/index.js +104 -52
- package/build/autocomplete/index.js.map +1 -1
- package/build/circular-option-picker/circular-option-picker-option.js +20 -39
- package/build/circular-option-picker/circular-option-picker-option.js.map +1 -1
- package/build/circular-option-picker/circular-option-picker.js +11 -32
- package/build/circular-option-picker/circular-option-picker.js.map +1 -1
- package/build/circular-option-picker/types.js.map +1 -1
- package/build/color-palette/index.js +7 -2
- package/build/color-palette/index.js.map +1 -1
- package/build/color-picker/component.js +12 -2
- package/build/color-picker/component.js.map +1 -1
- package/build/color-picker/picker.js +77 -1
- package/build/color-picker/picker.js.map +1 -1
- package/build/color-picker/styles.js +8 -8
- package/build/color-picker/styles.js.map +1 -1
- package/build/color-picker/types.js.map +1 -1
- package/build/composite/v2.js +43 -0
- package/build/composite/v2.js.map +1 -0
- package/build/confirm-dialog/component.js +74 -8
- package/build/confirm-dialog/component.js.map +1 -1
- package/build/confirm-dialog/types.js.map +1 -1
- package/build/custom-gradient-picker/gradient-bar/control-points.js +13 -4
- package/build/custom-gradient-picker/gradient-bar/control-points.js.map +1 -1
- package/build/dropdown-menu-v2-ariakit/index.js +217 -0
- package/build/dropdown-menu-v2-ariakit/index.js.map +1 -0
- package/build/dropdown-menu-v2-ariakit/styles.js +157 -0
- package/build/dropdown-menu-v2-ariakit/styles.js.map +1 -0
- package/build/dropdown-menu-v2-ariakit/types.js +6 -0
- package/build/dropdown-menu-v2-ariakit/types.js.map +1 -0
- package/build/font-size-picker/utils.js +1 -1
- package/build/font-size-picker/utils.js.map +1 -1
- package/build/input-control/styles/input-control-styles.js +23 -23
- package/build/input-control/styles/input-control-styles.js.map +1 -1
- package/build/mobile/global-styles-context/utils.native.js +1 -1
- package/build/mobile/global-styles-context/utils.native.js.map +1 -1
- package/build/modal/index.js +45 -16
- package/build/modal/index.js.map +1 -1
- package/build/palette-edit/index.js +4 -0
- package/build/palette-edit/index.js.map +1 -1
- package/build/popover/index.js +34 -6
- package/build/popover/index.js.map +1 -1
- package/build/private-apis.js +18 -2
- package/build/private-apis.js.map +1 -1
- package/build/progress-bar/styles.js +5 -5
- package/build/progress-bar/styles.js.map +1 -1
- package/build/sandbox/index.js +1 -1
- package/build/sandbox/index.js.map +1 -1
- package/build/sandbox/index.native.js +1 -1
- package/build/sandbox/index.native.js.map +1 -1
- package/build/select-control/styles/select-control-styles.js +8 -8
- package/build/select-control/styles/select-control-styles.js.map +1 -1
- package/build/tabs/context.js +16 -0
- package/build/tabs/context.js.map +1 -0
- package/build/tabs/index.js +147 -0
- package/build/tabs/index.js.map +1 -0
- package/build/tabs/styles.js +38 -0
- package/build/tabs/styles.js.map +1 -0
- package/build/tabs/tab.js +46 -0
- package/build/tabs/tab.js.map +1 -0
- package/build/tabs/tablist.js +47 -0
- package/build/tabs/tablist.js.map +1 -0
- package/build/tabs/tabpanel.js +48 -0
- package/build/tabs/tabpanel.js.map +1 -0
- package/build/tabs/types.js +6 -0
- package/build/tabs/types.js.map +1 -0
- package/build/text/component.js +7 -6
- package/build/text/component.js.map +1 -1
- package/build/text/hook.js +6 -15
- package/build/text/hook.js.map +1 -1
- package/build/text/index.js.map +1 -1
- package/build/text/styles.js +7 -7
- package/build/text/styles.js.map +1 -1
- package/build/text/types.js.map +1 -1
- package/build/text/utils.js +17 -33
- package/build/text/utils.js.map +1 -1
- package/build/toggle-group-control/toggle-group-control-option-base/component.js +1 -0
- package/build/toggle-group-control/toggle-group-control-option-base/component.js.map +1 -1
- package/build/toolbar/toolbar/index.js +17 -10
- package/build/toolbar/toolbar/index.js.map +1 -1
- package/build/toolbar/toolbar/types.js.map +1 -1
- package/build/tools-panel/tools-panel-item/hook.js +2 -2
- package/build/tools-panel/tools-panel-item/hook.js.map +1 -1
- package/build/tools-panel/types.js.map +1 -1
- package/build/tooltip/index.js +2 -2
- package/build/tooltip/index.js.map +1 -1
- package/build/unit-control/utils.js +108 -0
- package/build/unit-control/utils.js.map +1 -1
- package/build/utils/unit-values.js +1 -1
- package/build/utils/unit-values.js.map +1 -1
- package/build-module/alignment-matrix-control/cell.js +7 -4
- package/build-module/alignment-matrix-control/cell.js.map +1 -1
- package/build-module/alignment-matrix-control/index.js +27 -43
- package/build-module/alignment-matrix-control/index.js.map +1 -1
- package/build-module/alignment-matrix-control/utils.js +29 -8
- package/build-module/alignment-matrix-control/utils.js.map +1 -1
- package/build-module/autocomplete/index.js +104 -52
- package/build-module/autocomplete/index.js.map +1 -1
- package/build-module/circular-option-picker/circular-option-picker-option.js +20 -39
- package/build-module/circular-option-picker/circular-option-picker-option.js.map +1 -1
- package/build-module/circular-option-picker/circular-option-picker.js +10 -31
- package/build-module/circular-option-picker/circular-option-picker.js.map +1 -1
- package/build-module/circular-option-picker/types.js.map +1 -1
- package/build-module/color-palette/index.js +7 -2
- package/build-module/color-palette/index.js.map +1 -1
- package/build-module/color-picker/component.js +13 -3
- package/build-module/color-picker/component.js.map +1 -1
- package/build-module/color-picker/picker.js +78 -2
- package/build-module/color-picker/picker.js.map +1 -1
- package/build-module/color-picker/styles.js +8 -8
- package/build-module/color-picker/styles.js.map +1 -1
- package/build-module/color-picker/types.js.map +1 -1
- package/build-module/composite/v2.js +15 -0
- package/build-module/composite/v2.js.map +1 -0
- package/build-module/confirm-dialog/component.js +72 -7
- package/build-module/confirm-dialog/component.js.map +1 -1
- package/build-module/confirm-dialog/types.js.map +1 -1
- package/build-module/custom-gradient-picker/gradient-bar/control-points.js +13 -4
- package/build-module/custom-gradient-picker/gradient-bar/control-points.js.map +1 -1
- package/build-module/dropdown-menu-v2-ariakit/index.js +199 -0
- package/build-module/dropdown-menu-v2-ariakit/index.js.map +1 -0
- package/build-module/dropdown-menu-v2-ariakit/styles.js +136 -0
- package/build-module/dropdown-menu-v2-ariakit/styles.js.map +1 -0
- package/build-module/dropdown-menu-v2-ariakit/types.js +2 -0
- package/build-module/dropdown-menu-v2-ariakit/types.js.map +1 -0
- package/build-module/font-size-picker/utils.js +1 -1
- package/build-module/font-size-picker/utils.js.map +1 -1
- package/build-module/input-control/styles/input-control-styles.js +23 -23
- package/build-module/input-control/styles/input-control-styles.js.map +1 -1
- package/build-module/mobile/global-styles-context/utils.native.js +2 -2
- package/build-module/mobile/global-styles-context/utils.native.js.map +1 -1
- package/build-module/modal/index.js +47 -18
- package/build-module/modal/index.js.map +1 -1
- package/build-module/palette-edit/index.js +4 -0
- package/build-module/palette-edit/index.js.map +1 -1
- package/build-module/popover/index.js +34 -6
- package/build-module/popover/index.js.map +1 -1
- package/build-module/private-apis.js +18 -2
- package/build-module/private-apis.js.map +1 -1
- package/build-module/progress-bar/styles.js +5 -5
- package/build-module/progress-bar/styles.js.map +1 -1
- package/build-module/sandbox/index.js +1 -1
- package/build-module/sandbox/index.js.map +1 -1
- package/build-module/sandbox/index.native.js +1 -1
- package/build-module/sandbox/index.native.js.map +1 -1
- package/build-module/select-control/styles/select-control-styles.js +8 -8
- package/build-module/select-control/styles/select-control-styles.js.map +1 -1
- package/build-module/tabs/context.js +12 -0
- package/build-module/tabs/context.js.map +1 -0
- package/build-module/tabs/index.js +142 -0
- package/build-module/tabs/index.js.map +1 -0
- package/build-module/tabs/styles.js +36 -0
- package/build-module/tabs/styles.js.map +1 -0
- package/build-module/tabs/tab.js +43 -0
- package/build-module/tabs/tab.js.map +1 -0
- package/build-module/tabs/tablist.js +41 -0
- package/build-module/tabs/tablist.js.map +1 -0
- package/build-module/tabs/tabpanel.js +43 -0
- package/build-module/tabs/tabpanel.js.map +1 -0
- package/build-module/tabs/types.js +2 -0
- package/build-module/tabs/types.js.map +1 -0
- package/build-module/text/component.js +6 -6
- package/build-module/text/component.js.map +1 -1
- package/build-module/text/hook.js +11 -19
- package/build-module/text/hook.js.map +1 -1
- package/build-module/text/index.js.map +1 -1
- package/build-module/text/styles.js +7 -7
- package/build-module/text/styles.js.map +1 -1
- package/build-module/text/types.js.map +1 -1
- package/build-module/text/utils.js +17 -10
- package/build-module/text/utils.js.map +1 -1
- package/build-module/toggle-group-control/toggle-group-control-option-base/component.js +1 -0
- package/build-module/toggle-group-control/toggle-group-control-option-base/component.js.map +1 -1
- package/build-module/toolbar/toolbar/index.js +18 -11
- package/build-module/toolbar/toolbar/index.js.map +1 -1
- package/build-module/toolbar/toolbar/types.js.map +1 -1
- package/build-module/tools-panel/tools-panel-item/hook.js +2 -2
- package/build-module/tools-panel/tools-panel-item/hook.js.map +1 -1
- package/build-module/tools-panel/types.js.map +1 -1
- package/build-module/tooltip/index.js +2 -2
- package/build-module/tooltip/index.js.map +1 -1
- package/build-module/unit-control/utils.js +108 -0
- package/build-module/unit-control/utils.js.map +1 -1
- package/build-module/utils/unit-values.js +1 -1
- package/build-module/utils/unit-values.js.map +1 -1
- package/build-style/style-rtl.css +17 -5
- package/build-style/style.css +17 -5
- package/build-types/alignment-matrix-control/cell.d.ts +1 -1
- package/build-types/alignment-matrix-control/cell.d.ts.map +1 -1
- package/build-types/alignment-matrix-control/index.d.ts.map +1 -1
- package/build-types/alignment-matrix-control/stories/index.story.d.ts.map +1 -1
- package/build-types/alignment-matrix-control/utils.d.ts +9 -9
- package/build-types/alignment-matrix-control/utils.d.ts.map +1 -1
- package/build-types/autocomplete/index.d.ts.map +1 -1
- package/build-types/circular-option-picker/circular-option-picker-option.d.ts.map +1 -1
- package/build-types/circular-option-picker/circular-option-picker.d.ts.map +1 -1
- package/build-types/circular-option-picker/types.d.ts +4 -6
- package/build-types/circular-option-picker/types.d.ts.map +1 -1
- package/build-types/color-palette/index.d.ts.map +1 -1
- package/build-types/color-picker/component.d.ts.map +1 -1
- package/build-types/color-picker/picker.d.ts +1 -1
- package/build-types/color-picker/picker.d.ts.map +1 -1
- package/build-types/color-picker/styles.d.ts.map +1 -1
- package/build-types/color-picker/types.d.ts +3 -0
- package/build-types/color-picker/types.d.ts.map +1 -1
- package/build-types/composite/v2.d.ts +12 -0
- package/build-types/composite/v2.d.ts.map +1 -0
- package/build-types/confirm-dialog/component.d.ts +70 -29
- package/build-types/confirm-dialog/component.d.ts.map +1 -1
- package/build-types/confirm-dialog/stories/index.story.d.ts +11 -0
- package/build-types/confirm-dialog/stories/index.story.d.ts.map +1 -0
- package/build-types/confirm-dialog/test/index.d.ts +2 -0
- package/build-types/confirm-dialog/test/index.d.ts.map +1 -0
- package/build-types/confirm-dialog/types.d.ts +32 -10
- package/build-types/confirm-dialog/types.d.ts.map +1 -1
- package/build-types/custom-gradient-picker/gradient-bar/control-points.d.ts.map +1 -1
- package/build-types/dropdown-menu-v2-ariakit/index.d.ts +11 -0
- package/build-types/dropdown-menu-v2-ariakit/index.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/stories/index.story.d.ts +16 -0
- package/build-types/dropdown-menu-v2-ariakit/stories/index.story.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/styles.d.ts +88 -0
- package/build-types/dropdown-menu-v2-ariakit/styles.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/test/index.d.ts +2 -0
- package/build-types/dropdown-menu-v2-ariakit/test/index.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/types.d.ts +174 -0
- package/build-types/dropdown-menu-v2-ariakit/types.d.ts.map +1 -0
- package/build-types/font-size-picker/utils.d.ts.map +1 -1
- package/build-types/heading/stories/index.story.d.ts.map +1 -1
- package/build-types/modal/index.d.ts.map +1 -1
- package/build-types/palette-edit/index.d.ts.map +1 -1
- package/build-types/popover/index.d.ts +1 -1
- package/build-types/popover/index.d.ts.map +1 -1
- package/build-types/popover/stories/e2e/index.story.d.ts +1 -1
- package/build-types/private-apis.d.ts.map +1 -1
- package/build-types/progress-bar/styles.d.ts.map +1 -1
- package/build-types/sandbox/index.d.ts.map +1 -1
- package/build-types/tabs/context.d.ts +8 -0
- package/build-types/tabs/context.d.ts.map +1 -0
- package/build-types/tabs/index.d.ts +13 -0
- package/build-types/tabs/index.d.ts.map +1 -0
- package/build-types/tabs/stories/index.story.d.ts +20 -0
- package/build-types/tabs/stories/index.story.d.ts.map +1 -0
- package/build-types/tabs/styles.d.ts +17 -0
- package/build-types/tabs/styles.d.ts.map +1 -0
- package/build-types/tabs/tab.d.ts +10 -0
- package/build-types/tabs/tab.d.ts.map +1 -0
- package/build-types/tabs/tablist.d.ts +7 -0
- package/build-types/tabs/tablist.d.ts.map +1 -0
- package/build-types/tabs/tabpanel.d.ts +7 -0
- package/build-types/tabs/tabpanel.d.ts.map +1 -0
- package/build-types/tabs/test/index.d.ts +2 -0
- package/build-types/tabs/test/index.d.ts.map +1 -0
- package/build-types/tabs/types.d.ts +134 -0
- package/build-types/tabs/types.d.ts.map +1 -0
- package/build-types/text/component.d.ts +4 -2
- package/build-types/text/component.d.ts.map +1 -1
- package/build-types/text/hook.d.ts +171 -165
- package/build-types/text/hook.d.ts.map +1 -1
- package/build-types/text/index.d.ts +2 -2
- package/build-types/text/index.d.ts.map +1 -1
- package/build-types/text/stories/index.story.d.ts +21 -0
- package/build-types/text/stories/index.story.d.ts.map +1 -0
- package/build-types/text/styles.d.ts +7 -7
- package/build-types/text/styles.d.ts.map +1 -1
- package/build-types/text/types.d.ts +1 -1
- package/build-types/text/types.d.ts.map +1 -1
- package/build-types/text/utils.d.ts +56 -61
- package/build-types/text/utils.d.ts.map +1 -1
- package/build-types/toggle-group-control/toggle-group-control-option-base/component.d.ts.map +1 -1
- package/build-types/toolbar/stories/index.story.d.ts +5 -0
- package/build-types/toolbar/stories/index.story.d.ts.map +1 -1
- package/build-types/toolbar/toolbar/index.d.ts.map +1 -1
- package/build-types/toolbar/toolbar/types.d.ts +10 -0
- package/build-types/toolbar/toolbar/types.d.ts.map +1 -1
- package/build-types/tools-panel/tools-panel-item/hook.d.ts.map +1 -1
- package/build-types/tools-panel/types.d.ts +2 -0
- package/build-types/tools-panel/types.d.ts.map +1 -1
- package/build-types/tooltip/index.d.ts.map +1 -1
- package/build-types/unit-control/utils.d.ts.map +1 -1
- package/package.json +21 -20
- package/src/alignment-matrix-control/cell.tsx +6 -2
- package/src/alignment-matrix-control/index.tsx +31 -54
- package/src/alignment-matrix-control/stories/index.story.tsx +3 -7
- package/src/alignment-matrix-control/test/index.tsx +117 -18
- package/src/alignment-matrix-control/utils.tsx +33 -9
- package/src/autocomplete/index.tsx +136 -77
- package/src/button/style.scss +1 -2
- package/src/circular-option-picker/circular-option-picker-option.tsx +24 -38
- package/src/circular-option-picker/circular-option-picker.tsx +11 -28
- package/src/circular-option-picker/types.ts +6 -5
- package/src/color-palette/index.tsx +6 -1
- package/src/color-picker/component.tsx +25 -3
- package/src/color-picker/picker.tsx +96 -2
- package/src/color-picker/styles.ts +0 -1
- package/src/color-picker/types.ts +3 -0
- package/src/composite/v2.ts +22 -0
- package/src/confirm-dialog/README.md +1 -1
- package/src/confirm-dialog/component.tsx +79 -13
- package/src/confirm-dialog/stories/{index.story.js → index.story.tsx} +26 -24
- package/src/confirm-dialog/test/{index.js → index.tsx} +3 -3
- package/src/confirm-dialog/types.ts +32 -12
- package/src/custom-gradient-picker/gradient-bar/control-points.tsx +32 -25
- package/src/dimension-control/test/__snapshots__/index.test.js.snap +8 -8
- package/src/dropdown-menu-v2-ariakit/README.md +324 -0
- package/src/dropdown-menu-v2-ariakit/index.tsx +318 -0
- package/src/dropdown-menu-v2-ariakit/stories/index.story.tsx +506 -0
- package/src/dropdown-menu-v2-ariakit/styles.ts +297 -0
- package/src/dropdown-menu-v2-ariakit/test/index.tsx +1139 -0
- package/src/dropdown-menu-v2-ariakit/types.ts +186 -0
- package/src/font-size-picker/utils.ts +2 -1
- package/src/heading/stories/index.story.tsx +2 -4
- package/src/input-control/styles/input-control-styles.tsx +2 -2
- package/src/mobile/global-styles-context/utils.native.js +2 -2
- package/src/modal/index.tsx +58 -22
- package/src/modal/test/index.tsx +29 -0
- package/src/notice/style.scss +0 -1
- package/src/palette-edit/index.tsx +4 -0
- package/src/popover/index.tsx +99 -57
- package/src/popover/style.scss +9 -0
- package/src/private-apis.ts +31 -1
- package/src/progress-bar/styles.ts +19 -4
- package/src/sandbox/index.native.js +1 -1
- package/src/sandbox/index.tsx +3 -1
- package/src/select-control/styles/select-control-styles.ts +2 -2
- package/src/tabs/README.md +242 -0
- package/src/tabs/context.ts +13 -0
- package/src/tabs/index.tsx +167 -0
- package/src/tabs/stories/index.story.tsx +352 -0
- package/src/tabs/styles.ts +103 -0
- package/src/tabs/tab.tsx +39 -0
- package/src/tabs/tablist.tsx +40 -0
- package/src/tabs/tabpanel.tsx +42 -0
- package/src/tabs/test/index.tsx +1133 -0
- package/src/tabs/types.ts +142 -0
- package/src/text/README.md +2 -2
- package/src/text/{component.js → component.tsx} +10 -6
- package/src/text/{hook.js → hook.ts} +12 -15
- package/src/text/stories/index.story.tsx +80 -0
- package/src/text/types.ts +1 -6
- package/src/text/{utils.js → utils.ts} +40 -14
- package/src/toggle-group-control/test/__snapshots__/index.tsx.snap +16 -0
- package/src/toggle-group-control/toggle-group-control-option-base/component.tsx +1 -0
- package/src/toolbar/stories/index.story.tsx +15 -0
- package/src/toolbar/test/index.tsx +8 -0
- package/src/toolbar/toolbar/README.md +9 -0
- package/src/toolbar/toolbar/index.tsx +21 -12
- package/src/toolbar/toolbar/style.scss +9 -0
- package/src/toolbar/toolbar/types.ts +10 -0
- package/src/tools-panel/tools-panel/README.md +3 -0
- package/src/tools-panel/tools-panel-item/hook.ts +4 -6
- package/src/tools-panel/types.ts +2 -0
- package/src/tooltip/index.tsx +2 -3
- package/src/unit-control/utils.ts +124 -0
- package/src/utils/unit-values.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/src/text/stories/index.story.js +0 -53
- /package/src/text/{index.js → index.ts} +0 -0
- /package/src/text/{styles.js → styles.ts} +0 -0
|
@@ -22,6 +22,8 @@ import {
|
|
|
22
22
|
isCollapsed,
|
|
23
23
|
getTextContent,
|
|
24
24
|
} from '@wordpress/rich-text';
|
|
25
|
+
import { speak } from '@wordpress/a11y';
|
|
26
|
+
import { isAppleOS } from '@wordpress/keycodes';
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
29
|
* Internal dependencies
|
|
@@ -39,6 +41,35 @@ import type {
|
|
|
39
41
|
WPCompleter,
|
|
40
42
|
} from './types';
|
|
41
43
|
|
|
44
|
+
const getNodeText = ( node: React.ReactNode ): string => {
|
|
45
|
+
if ( node === null ) {
|
|
46
|
+
return '';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
switch ( typeof node ) {
|
|
50
|
+
case 'string':
|
|
51
|
+
case 'number':
|
|
52
|
+
return node.toString();
|
|
53
|
+
break;
|
|
54
|
+
case 'boolean':
|
|
55
|
+
return '';
|
|
56
|
+
break;
|
|
57
|
+
case 'object': {
|
|
58
|
+
if ( node instanceof Array ) {
|
|
59
|
+
return node.map( getNodeText ).join( '' );
|
|
60
|
+
}
|
|
61
|
+
if ( 'props' in node ) {
|
|
62
|
+
return getNodeText( node.props.children );
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
default:
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return '';
|
|
71
|
+
};
|
|
72
|
+
|
|
42
73
|
const EMPTY_FILTERED_OPTIONS: KeyedOption[] = [];
|
|
43
74
|
|
|
44
75
|
export function useAutocomplete( {
|
|
@@ -163,20 +194,35 @@ export function useAutocomplete( {
|
|
|
163
194
|
) {
|
|
164
195
|
return;
|
|
165
196
|
}
|
|
197
|
+
|
|
166
198
|
switch ( event.key ) {
|
|
167
|
-
case 'ArrowUp':
|
|
168
|
-
|
|
199
|
+
case 'ArrowUp': {
|
|
200
|
+
const newIndex =
|
|
169
201
|
( selectedIndex === 0
|
|
170
202
|
? filteredOptions.length
|
|
171
|
-
: selectedIndex ) - 1
|
|
172
|
-
);
|
|
203
|
+
: selectedIndex ) - 1;
|
|
204
|
+
setSelectedIndex( newIndex );
|
|
205
|
+
// See the related PR as to why this is necessary: https://github.com/WordPress/gutenberg/pull/54902.
|
|
206
|
+
if ( isAppleOS() ) {
|
|
207
|
+
speak(
|
|
208
|
+
getNodeText( filteredOptions[ newIndex ].label ),
|
|
209
|
+
'assertive'
|
|
210
|
+
);
|
|
211
|
+
}
|
|
173
212
|
break;
|
|
213
|
+
}
|
|
174
214
|
|
|
175
|
-
case 'ArrowDown':
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
)
|
|
215
|
+
case 'ArrowDown': {
|
|
216
|
+
const newIndex = ( selectedIndex + 1 ) % filteredOptions.length;
|
|
217
|
+
setSelectedIndex( newIndex );
|
|
218
|
+
if ( isAppleOS() ) {
|
|
219
|
+
speak(
|
|
220
|
+
getNodeText( filteredOptions[ newIndex ].label ),
|
|
221
|
+
'assertive'
|
|
222
|
+
);
|
|
223
|
+
}
|
|
179
224
|
break;
|
|
225
|
+
}
|
|
180
226
|
|
|
181
227
|
case 'Escape':
|
|
182
228
|
setAutocompleter( null );
|
|
@@ -218,82 +264,95 @@ export function useAutocomplete( {
|
|
|
218
264
|
return;
|
|
219
265
|
}
|
|
220
266
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const textWithoutTrigger = textContent.slice(
|
|
230
|
-
index + triggerPrefix.length
|
|
267
|
+
// Find the completer with the highest triggerPrefix index in the
|
|
268
|
+
// textContent.
|
|
269
|
+
const completer = completers.reduce< WPCompleter | null >(
|
|
270
|
+
( lastTrigger, currentCompleter ) => {
|
|
271
|
+
const triggerIndex = textContent.lastIndexOf(
|
|
272
|
+
currentCompleter.triggerPrefix
|
|
231
273
|
);
|
|
274
|
+
const lastTriggerIndex =
|
|
275
|
+
lastTrigger !== null
|
|
276
|
+
? textContent.lastIndexOf( lastTrigger.triggerPrefix )
|
|
277
|
+
: -1;
|
|
278
|
+
|
|
279
|
+
return triggerIndex > lastTriggerIndex
|
|
280
|
+
? currentCompleter
|
|
281
|
+
: lastTrigger;
|
|
282
|
+
},
|
|
283
|
+
null
|
|
284
|
+
);
|
|
232
285
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
// is true and one of the "words" end up being too long. If that's the case,
|
|
238
|
-
// it will be caught by this guard.
|
|
239
|
-
if ( tooDistantFromTrigger ) return false;
|
|
240
|
-
|
|
241
|
-
const mismatch = filteredOptions.length === 0;
|
|
242
|
-
const wordsFromTrigger = textWithoutTrigger.split( /\s/ );
|
|
243
|
-
// We need to allow the effect to run when not backspacing and if there
|
|
244
|
-
// was a mismatch. i.e when typing a trigger + the match string or when
|
|
245
|
-
// clicking in an existing trigger word on the page. We do that if we
|
|
246
|
-
// detect that we have one word from trigger in the current textual context.
|
|
247
|
-
//
|
|
248
|
-
// Ex.: "Some text @a" <-- "@a" will be detected as the trigger word and
|
|
249
|
-
// allow the effect to run. It will run until there's a mismatch.
|
|
250
|
-
const hasOneTriggerWord = wordsFromTrigger.length === 1;
|
|
251
|
-
// This is used to allow the effect to run when backspacing and if
|
|
252
|
-
// "touching" a word that "belongs" to a trigger. We consider a "trigger
|
|
253
|
-
// word" any word up to the limit of 3 from the trigger character.
|
|
254
|
-
// Anything beyond that is ignored if there's a mismatch. This allows
|
|
255
|
-
// us to "escape" a mismatch when backspacing, but still imposing some
|
|
256
|
-
// sane limits.
|
|
257
|
-
//
|
|
258
|
-
// Ex: "Some text @marcelo sekkkk" <--- "kkkk" caused a mismatch, but
|
|
259
|
-
// if the user presses backspace here, it will show the completion popup again.
|
|
260
|
-
const matchingWhileBackspacing =
|
|
261
|
-
backspacing.current &&
|
|
262
|
-
textWithoutTrigger.split( /\s/ ).length <= 3;
|
|
263
|
-
|
|
264
|
-
if (
|
|
265
|
-
mismatch &&
|
|
266
|
-
! ( matchingWhileBackspacing || hasOneTriggerWord )
|
|
267
|
-
) {
|
|
268
|
-
return false;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const textAfterSelection = getTextContent(
|
|
272
|
-
slice( record, undefined, getTextContent( record ).length )
|
|
273
|
-
);
|
|
286
|
+
if ( ! completer ) {
|
|
287
|
+
if ( autocompleter ) reset();
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
274
290
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
)
|
|
281
|
-
) {
|
|
282
|
-
return false;
|
|
283
|
-
}
|
|
291
|
+
const { allowContext, triggerPrefix } = completer;
|
|
292
|
+
const triggerIndex = textContent.lastIndexOf( triggerPrefix );
|
|
293
|
+
const textWithoutTrigger = textContent.slice(
|
|
294
|
+
triggerIndex + triggerPrefix.length
|
|
295
|
+
);
|
|
284
296
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
297
|
+
const tooDistantFromTrigger = textWithoutTrigger.length > 50; // 50 chars seems to be a good limit.
|
|
298
|
+
// This is a final barrier to prevent the effect from completing with
|
|
299
|
+
// an extremely long string, which causes the editor to slow-down
|
|
300
|
+
// significantly. This could happen, for example, if `matchingWhileBackspacing`
|
|
301
|
+
// is true and one of the "words" end up being too long. If that's the case,
|
|
302
|
+
// it will be caught by this guard.
|
|
303
|
+
if ( tooDistantFromTrigger ) return;
|
|
304
|
+
|
|
305
|
+
const mismatch = filteredOptions.length === 0;
|
|
306
|
+
const wordsFromTrigger = textWithoutTrigger.split( /\s/ );
|
|
307
|
+
// We need to allow the effect to run when not backspacing and if there
|
|
308
|
+
// was a mismatch. i.e when typing a trigger + the match string or when
|
|
309
|
+
// clicking in an existing trigger word on the page. We do that if we
|
|
310
|
+
// detect that we have one word from trigger in the current textual context.
|
|
311
|
+
//
|
|
312
|
+
// Ex.: "Some text @a" <-- "@a" will be detected as the trigger word and
|
|
313
|
+
// allow the effect to run. It will run until there's a mismatch.
|
|
314
|
+
const hasOneTriggerWord = wordsFromTrigger.length === 1;
|
|
315
|
+
// This is used to allow the effect to run when backspacing and if
|
|
316
|
+
// "touching" a word that "belongs" to a trigger. We consider a "trigger
|
|
317
|
+
// word" any word up to the limit of 3 from the trigger character.
|
|
318
|
+
// Anything beyond that is ignored if there's a mismatch. This allows
|
|
319
|
+
// us to "escape" a mismatch when backspacing, but still imposing some
|
|
320
|
+
// sane limits.
|
|
321
|
+
//
|
|
322
|
+
// Ex: "Some text @marcelo sekkkk" <--- "kkkk" caused a mismatch, but
|
|
323
|
+
// if the user presses backspace here, it will show the completion popup again.
|
|
324
|
+
const matchingWhileBackspacing =
|
|
325
|
+
backspacing.current && wordsFromTrigger.length <= 3;
|
|
326
|
+
|
|
327
|
+
if ( mismatch && ! ( matchingWhileBackspacing || hasOneTriggerWord ) ) {
|
|
328
|
+
if ( autocompleter ) reset();
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
291
331
|
|
|
292
|
-
|
|
293
|
-
|
|
332
|
+
const textAfterSelection = getTextContent(
|
|
333
|
+
slice( record, undefined, getTextContent( record ).length )
|
|
294
334
|
);
|
|
295
335
|
|
|
296
|
-
if (
|
|
336
|
+
if (
|
|
337
|
+
allowContext &&
|
|
338
|
+
! allowContext(
|
|
339
|
+
textContent.slice( 0, triggerIndex ),
|
|
340
|
+
textAfterSelection
|
|
341
|
+
)
|
|
342
|
+
) {
|
|
343
|
+
if ( autocompleter ) reset();
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (
|
|
348
|
+
/^\s/.test( textWithoutTrigger ) ||
|
|
349
|
+
/\s\s+$/.test( textWithoutTrigger )
|
|
350
|
+
) {
|
|
351
|
+
if ( autocompleter ) reset();
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if ( ! /[\u0000-\uFFFF]*$/.test( textWithoutTrigger ) ) {
|
|
297
356
|
if ( autocompleter ) reset();
|
|
298
357
|
return;
|
|
299
358
|
}
|
package/src/button/style.scss
CHANGED
|
@@ -8,7 +8,7 @@ import type { ForwardedRef } from 'react';
|
|
|
8
8
|
* WordPress dependencies
|
|
9
9
|
*/
|
|
10
10
|
import { useInstanceId } from '@wordpress/compose';
|
|
11
|
-
import { forwardRef, useContext
|
|
11
|
+
import { forwardRef, useContext } from '@wordpress/element';
|
|
12
12
|
import { Icon, check } from '@wordpress/icons';
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -16,15 +16,9 @@ import { Icon, check } from '@wordpress/icons';
|
|
|
16
16
|
*/
|
|
17
17
|
import { CircularOptionPickerContext } from './circular-option-picker-context';
|
|
18
18
|
import Button from '../button';
|
|
19
|
-
import { CompositeItem } from '../composite';
|
|
19
|
+
import { CompositeItem } from '../composite/v2';
|
|
20
20
|
import Tooltip from '../tooltip';
|
|
21
|
-
import type {
|
|
22
|
-
OptionProps,
|
|
23
|
-
CircularOptionPickerCompositeState,
|
|
24
|
-
CircularOptionPickerContextProps,
|
|
25
|
-
} from './types';
|
|
26
|
-
|
|
27
|
-
const hasSelectedOption = new Map();
|
|
21
|
+
import type { OptionProps, CircularOptionPickerCompositeStore } from './types';
|
|
28
22
|
|
|
29
23
|
function UnforwardedOptionAsButton(
|
|
30
24
|
props: {
|
|
@@ -40,7 +34,7 @@ function UnforwardedOptionAsButton(
|
|
|
40
34
|
{ ...additionalProps }
|
|
41
35
|
aria-pressed={ isPressed }
|
|
42
36
|
ref={ forwardedRef }
|
|
43
|
-
|
|
37
|
+
/>
|
|
44
38
|
);
|
|
45
39
|
}
|
|
46
40
|
|
|
@@ -51,38 +45,29 @@ function UnforwardedOptionAsOption(
|
|
|
51
45
|
id: string;
|
|
52
46
|
className?: string;
|
|
53
47
|
isSelected?: boolean;
|
|
54
|
-
|
|
48
|
+
compositeStore: CircularOptionPickerCompositeStore;
|
|
55
49
|
},
|
|
56
50
|
forwardedRef: ForwardedRef< any >
|
|
57
51
|
) {
|
|
58
|
-
const { id, isSelected,
|
|
59
|
-
const
|
|
60
|
-
const compositeState =
|
|
61
|
-
_compositeState as CircularOptionPickerCompositeState;
|
|
62
|
-
const { baseId, currentId, setCurrentId } = compositeState;
|
|
52
|
+
const { id, isSelected, compositeStore, ...additionalProps } = props;
|
|
53
|
+
const activeId = compositeStore.useState( 'activeId' );
|
|
63
54
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
// map to make sure that we only set the first selected option.
|
|
68
|
-
// We still need to check `currentId` because the control will
|
|
69
|
-
// update this as the user moves around, and that state should
|
|
70
|
-
// be maintained as the group gains and loses focus.
|
|
71
|
-
if ( isSelected && ! currentId && ! hasSelectedOption.get( baseId ) ) {
|
|
72
|
-
hasSelectedOption.set( baseId, true );
|
|
73
|
-
setCurrentId( id );
|
|
74
|
-
}
|
|
75
|
-
}, [ baseId, currentId, id, isSelected, setCurrentId ] );
|
|
55
|
+
if ( isSelected && ! activeId ) {
|
|
56
|
+
compositeStore.setActiveId( id );
|
|
57
|
+
}
|
|
76
58
|
|
|
77
59
|
return (
|
|
78
60
|
<CompositeItem
|
|
79
|
-
{
|
|
80
|
-
|
|
81
|
-
|
|
61
|
+
render={
|
|
62
|
+
<Button
|
|
63
|
+
{ ...additionalProps }
|
|
64
|
+
role="option"
|
|
65
|
+
aria-selected={ !! isSelected }
|
|
66
|
+
ref={ forwardedRef }
|
|
67
|
+
/>
|
|
68
|
+
}
|
|
69
|
+
store={ compositeStore }
|
|
82
70
|
id={ id }
|
|
83
|
-
role="option"
|
|
84
|
-
aria-selected={ !! isSelected }
|
|
85
|
-
ref={ forwardedRef }
|
|
86
71
|
/>
|
|
87
72
|
);
|
|
88
73
|
}
|
|
@@ -96,8 +81,9 @@ export function Option( {
|
|
|
96
81
|
tooltipText,
|
|
97
82
|
...additionalProps
|
|
98
83
|
}: OptionProps ) {
|
|
99
|
-
const
|
|
100
|
-
|
|
84
|
+
const { baseId, compositeStore } = useContext(
|
|
85
|
+
CircularOptionPickerContext
|
|
86
|
+
);
|
|
101
87
|
const id = useInstanceId(
|
|
102
88
|
Option,
|
|
103
89
|
baseId || 'components-circular-option-picker__option'
|
|
@@ -109,10 +95,10 @@ export function Option( {
|
|
|
109
95
|
...additionalProps,
|
|
110
96
|
};
|
|
111
97
|
|
|
112
|
-
const optionControl =
|
|
98
|
+
const optionControl = compositeStore ? (
|
|
113
99
|
<OptionAsOption
|
|
114
100
|
{ ...commonProps }
|
|
115
|
-
|
|
101
|
+
compositeStore={ compositeStore }
|
|
116
102
|
isSelected={ isSelected }
|
|
117
103
|
/>
|
|
118
104
|
) : (
|
|
@@ -7,14 +7,13 @@ import classnames from 'classnames';
|
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
9
|
import { useInstanceId } from '@wordpress/compose';
|
|
10
|
-
import { useEffect } from '@wordpress/element';
|
|
11
10
|
import { isRTL } from '@wordpress/i18n';
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* Internal dependencies
|
|
15
14
|
*/
|
|
16
15
|
import { CircularOptionPickerContext } from './circular-option-picker-context';
|
|
17
|
-
import { Composite,
|
|
16
|
+
import { Composite, useCompositeStore } from '../composite/v2';
|
|
18
17
|
import type {
|
|
19
18
|
CircularOptionPickerProps,
|
|
20
19
|
ListboxCircularOptionPickerProps,
|
|
@@ -85,30 +84,15 @@ function ListboxCircularOptionPicker(
|
|
|
85
84
|
children,
|
|
86
85
|
...additionalProps
|
|
87
86
|
} = props;
|
|
88
|
-
const rtl = isRTL();
|
|
89
87
|
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
// the first render, so although unlikely to happen, if a state
|
|
95
|
-
// property should change, we need to process it accordingly.
|
|
96
|
-
|
|
97
|
-
useEffect( () => {
|
|
98
|
-
setBaseId( baseId );
|
|
99
|
-
}, [ setBaseId, baseId ] );
|
|
100
|
-
|
|
101
|
-
useEffect( () => {
|
|
102
|
-
setLoop( loop );
|
|
103
|
-
}, [ setLoop, loop ] );
|
|
104
|
-
|
|
105
|
-
useEffect( () => {
|
|
106
|
-
setRTL( rtl );
|
|
107
|
-
}, [ setRTL, rtl ] );
|
|
88
|
+
const compositeStore = useCompositeStore( {
|
|
89
|
+
focusLoop: loop,
|
|
90
|
+
rtl: isRTL(),
|
|
91
|
+
} );
|
|
108
92
|
|
|
109
93
|
const compositeContext = {
|
|
110
|
-
|
|
111
|
-
|
|
94
|
+
baseId,
|
|
95
|
+
compositeStore,
|
|
112
96
|
};
|
|
113
97
|
|
|
114
98
|
return (
|
|
@@ -116,7 +100,8 @@ function ListboxCircularOptionPicker(
|
|
|
116
100
|
<CircularOptionPickerContext.Provider value={ compositeContext }>
|
|
117
101
|
<Composite
|
|
118
102
|
{ ...additionalProps }
|
|
119
|
-
{
|
|
103
|
+
id={ baseId }
|
|
104
|
+
store={ compositeStore }
|
|
120
105
|
role={ 'listbox' }
|
|
121
106
|
>
|
|
122
107
|
{ options }
|
|
@@ -134,10 +119,8 @@ function ButtonsCircularOptionPicker(
|
|
|
134
119
|
const { actions, options, children, baseId, ...additionalProps } = props;
|
|
135
120
|
|
|
136
121
|
return (
|
|
137
|
-
<div { ...additionalProps }>
|
|
138
|
-
<CircularOptionPickerContext.Provider
|
|
139
|
-
value={ { isComposite: false, baseId } }
|
|
140
|
-
>
|
|
122
|
+
<div { ...additionalProps } id={ baseId }>
|
|
123
|
+
<CircularOptionPickerContext.Provider value={ { baseId } }>
|
|
141
124
|
{ options }
|
|
142
125
|
{ children }
|
|
143
126
|
{ actions }
|
|
@@ -14,7 +14,7 @@ import type { Icon } from '@wordpress/icons';
|
|
|
14
14
|
import type { ButtonAsButtonProps } from '../button/types';
|
|
15
15
|
import type { DropdownProps } from '../dropdown/types';
|
|
16
16
|
import type { WordPressComponentProps } from '../context';
|
|
17
|
-
import type {
|
|
17
|
+
import type { CompositeStore } from '../composite/v2';
|
|
18
18
|
|
|
19
19
|
type CommonCircularOptionPickerProps = {
|
|
20
20
|
/**
|
|
@@ -123,7 +123,8 @@ export type OptionProps = Omit<
|
|
|
123
123
|
>;
|
|
124
124
|
};
|
|
125
125
|
|
|
126
|
-
export type
|
|
127
|
-
export type CircularOptionPickerContextProps =
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
export type CircularOptionPickerCompositeStore = CompositeStore;
|
|
127
|
+
export type CircularOptionPickerContextProps = {
|
|
128
|
+
baseId?: string;
|
|
129
|
+
compositeStore?: CircularOptionPickerCompositeStore;
|
|
130
|
+
};
|
|
@@ -147,6 +147,10 @@ export function CustomColorPickerDropdown( {
|
|
|
147
147
|
const popoverProps = useMemo< DropdownProps[ 'popoverProps' ] >(
|
|
148
148
|
() => ( {
|
|
149
149
|
shift: true,
|
|
150
|
+
// Disabling resize as it would otherwise cause the popover to show
|
|
151
|
+
// scrollbars while dragging the color picker's handle close to the
|
|
152
|
+
// popover edge.
|
|
153
|
+
resize: false,
|
|
150
154
|
...( isRenderedInSidebar
|
|
151
155
|
? {
|
|
152
156
|
// When in the sidebar: open to the left (stacking),
|
|
@@ -299,6 +303,7 @@ function UnforwardedColorPalette(
|
|
|
299
303
|
style={ {
|
|
300
304
|
background: value,
|
|
301
305
|
} }
|
|
306
|
+
type="button"
|
|
302
307
|
/>
|
|
303
308
|
<VStack
|
|
304
309
|
className="components-color-palette__custom-color-text-wrapper"
|
|
@@ -307,7 +312,7 @@ function UnforwardedColorPalette(
|
|
|
307
312
|
<Truncate className="components-color-palette__custom-color-name">
|
|
308
313
|
{ value
|
|
309
314
|
? buttonLabelName
|
|
310
|
-
: 'No color selected' }
|
|
315
|
+
: __( 'No color selected' ) }
|
|
311
316
|
</Truncate>
|
|
312
317
|
{ /*
|
|
313
318
|
This `Truncate` is always rendered, even if
|
|
@@ -10,7 +10,7 @@ import namesPlugin from 'colord/plugins/names';
|
|
|
10
10
|
* WordPress dependencies
|
|
11
11
|
*/
|
|
12
12
|
import { useCallback, useState, useMemo } from '@wordpress/element';
|
|
13
|
-
import { useDebounce } from '@wordpress/compose';
|
|
13
|
+
import { useDebounce, useMergeRefs } from '@wordpress/compose';
|
|
14
14
|
import { __ } from '@wordpress/i18n';
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -49,8 +49,24 @@ const UnconnectedColorPicker = (
|
|
|
49
49
|
onChange,
|
|
50
50
|
defaultValue = '#fff',
|
|
51
51
|
copyFormat,
|
|
52
|
+
|
|
53
|
+
// Context
|
|
54
|
+
onPickerDragStart,
|
|
55
|
+
onPickerDragEnd,
|
|
52
56
|
...divProps
|
|
53
|
-
} = useContextSystem
|
|
57
|
+
} = useContextSystem<
|
|
58
|
+
ColorPickerProps & {
|
|
59
|
+
onPickerDragStart?: ( event: MouseEvent ) => void;
|
|
60
|
+
onPickerDragEnd?: ( event: MouseEvent ) => void;
|
|
61
|
+
}
|
|
62
|
+
>( props, 'ColorPicker' );
|
|
63
|
+
|
|
64
|
+
const [ containerEl, setContainerEl ] = useState< HTMLElement | null >(
|
|
65
|
+
null
|
|
66
|
+
);
|
|
67
|
+
const containerRef = ( node: HTMLElement | null ) => {
|
|
68
|
+
setContainerEl( node );
|
|
69
|
+
};
|
|
54
70
|
|
|
55
71
|
// Use a safe default value for the color and remove the possibility of `undefined`.
|
|
56
72
|
const [ color, setColor ] = useControlledValue( {
|
|
@@ -77,11 +93,17 @@ const UnconnectedColorPicker = (
|
|
|
77
93
|
);
|
|
78
94
|
|
|
79
95
|
return (
|
|
80
|
-
<ColorfulWrapper
|
|
96
|
+
<ColorfulWrapper
|
|
97
|
+
ref={ useMergeRefs( [ containerRef, forwardedRef ] ) }
|
|
98
|
+
{ ...divProps }
|
|
99
|
+
>
|
|
81
100
|
<Picker
|
|
101
|
+
containerEl={ containerEl }
|
|
82
102
|
onChange={ handleChange }
|
|
83
103
|
color={ safeColordColor }
|
|
84
104
|
enableAlpha={ enableAlpha }
|
|
105
|
+
onDragStart={ onPickerDragStart }
|
|
106
|
+
onDragEnd={ onPickerDragEnd }
|
|
85
107
|
/>
|
|
86
108
|
<AuxiliaryColorArtefactWrapper>
|
|
87
109
|
<AuxiliaryColorArtefactHStackHeader justify="space-between">
|
|
@@ -7,18 +7,112 @@ import { colord } from 'colord';
|
|
|
7
7
|
/**
|
|
8
8
|
* WordPress dependencies
|
|
9
9
|
*/
|
|
10
|
-
import { useMemo } from '@wordpress/element';
|
|
10
|
+
import { useMemo, useEffect, useRef } from '@wordpress/element';
|
|
11
11
|
/**
|
|
12
12
|
* Internal dependencies
|
|
13
13
|
*/
|
|
14
14
|
import type { PickerProps } from './types';
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Track the start and the end of drag pointer events related to controlling
|
|
18
|
+
* the picker's saturation / hue / alpha, and fire the corresponding callbacks.
|
|
19
|
+
* This is particularly useful to implement synergies like the one with the
|
|
20
|
+
* `Popover` component, where a pointer events "trap" is rendered while
|
|
21
|
+
* the user is dragging the pointer to avoid potential interference with iframe
|
|
22
|
+
* elements.
|
|
23
|
+
*
|
|
24
|
+
* @param props
|
|
25
|
+
* @param props.containerEl
|
|
26
|
+
* @param props.onDragStart
|
|
27
|
+
* @param props.onDragEnd
|
|
28
|
+
*/
|
|
29
|
+
const useOnPickerDrag = ( {
|
|
30
|
+
containerEl,
|
|
31
|
+
onDragStart,
|
|
32
|
+
onDragEnd,
|
|
33
|
+
}: Pick< PickerProps, 'containerEl' | 'onDragStart' | 'onDragEnd' > ) => {
|
|
34
|
+
const isDragging = useRef( false );
|
|
35
|
+
const leftWhileDragging = useRef( false );
|
|
36
|
+
useEffect( () => {
|
|
37
|
+
if ( ! containerEl || ( ! onDragStart && ! onDragEnd ) ) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const interactiveElements = [
|
|
41
|
+
containerEl.querySelector( '.react-colorful__saturation' ),
|
|
42
|
+
containerEl.querySelector( '.react-colorful__hue' ),
|
|
43
|
+
containerEl.querySelector( '.react-colorful__alpha' ),
|
|
44
|
+
].filter( ( el ) => !! el ) as Element[];
|
|
45
|
+
|
|
46
|
+
if ( interactiveElements.length === 0 ) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const doc = containerEl.ownerDocument;
|
|
51
|
+
|
|
52
|
+
const onPointerUp: EventListener = ( event ) => {
|
|
53
|
+
isDragging.current = false;
|
|
54
|
+
leftWhileDragging.current = false;
|
|
55
|
+
onDragEnd?.( event as MouseEvent );
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const onPointerDown: EventListener = ( event ) => {
|
|
59
|
+
isDragging.current = true;
|
|
60
|
+
onDragStart?.( event as MouseEvent );
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const onPointerLeave: EventListener = () => {
|
|
64
|
+
leftWhileDragging.current = isDragging.current;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Try to detect if the user released the pointer while away from the
|
|
68
|
+
// current window. If the check is successfull, the dragEnd callback will
|
|
69
|
+
// called as soon as the pointer re-enters the window (better late than never)
|
|
70
|
+
const onPointerEnter: EventListener = ( event ) => {
|
|
71
|
+
const noPointerButtonsArePressed =
|
|
72
|
+
( event as PointerEvent ).buttons === 0;
|
|
73
|
+
|
|
74
|
+
if ( leftWhileDragging.current && noPointerButtonsArePressed ) {
|
|
75
|
+
onPointerUp( event );
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// The pointerdown event is added on the interactive elements,
|
|
80
|
+
// while the remaining events are added on the document object since
|
|
81
|
+
// the pointer wouldn't necessarily be hovering the initial interactive
|
|
82
|
+
// element at that point.
|
|
83
|
+
interactiveElements.forEach( ( el ) =>
|
|
84
|
+
el.addEventListener( 'pointerdown', onPointerDown )
|
|
85
|
+
);
|
|
86
|
+
doc.addEventListener( 'pointerup', onPointerUp );
|
|
87
|
+
doc.addEventListener( 'pointerenter', onPointerEnter );
|
|
88
|
+
doc.addEventListener( 'pointerleave', onPointerLeave );
|
|
89
|
+
|
|
90
|
+
return () => {
|
|
91
|
+
interactiveElements.forEach( ( el ) =>
|
|
92
|
+
el.removeEventListener( 'pointerdown', onPointerDown )
|
|
93
|
+
);
|
|
94
|
+
doc.removeEventListener( 'pointerup', onPointerUp );
|
|
95
|
+
doc.removeEventListener( 'pointerenter', onPointerEnter );
|
|
96
|
+
doc.removeEventListener( 'pointerleave', onPointerUp );
|
|
97
|
+
};
|
|
98
|
+
}, [ onDragStart, onDragEnd, containerEl ] );
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const Picker = ( {
|
|
102
|
+
color,
|
|
103
|
+
enableAlpha,
|
|
104
|
+
onChange,
|
|
105
|
+
onDragStart,
|
|
106
|
+
onDragEnd,
|
|
107
|
+
containerEl,
|
|
108
|
+
}: PickerProps ) => {
|
|
17
109
|
const Component = enableAlpha
|
|
18
110
|
? RgbaStringColorPicker
|
|
19
111
|
: RgbStringColorPicker;
|
|
20
112
|
const rgbColor = useMemo( () => color.toRgbString(), [ color ] );
|
|
21
113
|
|
|
114
|
+
useOnPickerDrag( { containerEl, onDragStart, onDragEnd } );
|
|
115
|
+
|
|
22
116
|
return (
|
|
23
117
|
<Component
|
|
24
118
|
color={ rgbColor }
|