@wordpress/components 25.10.0 → 25.11.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 +16 -0
- package/build/autocomplete/index.js +104 -52
- package/build/autocomplete/index.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/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/private-apis.js +9 -1
- package/build/private-apis.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/slot-fill/bubbles-virtually/slot-fill-provider.js +1 -1
- package/build/slot-fill/bubbles-virtually/slot-fill-provider.js.map +1 -1
- package/build/tabs/index.js +2 -2
- package/build/tabs/index.js.map +1 -1
- package/build/tooltip/index.js +2 -2
- package/build/tooltip/index.js.map +1 -1
- package/build-module/autocomplete/index.js +104 -52
- package/build-module/autocomplete/index.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/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/private-apis.js +9 -1
- package/build-module/private-apis.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/slot-fill/bubbles-virtually/slot-fill-provider.js +1 -1
- package/build-module/slot-fill/bubbles-virtually/slot-fill-provider.js.map +1 -1
- package/build-module/tabs/index.js +3 -3
- package/build-module/tabs/index.js.map +1 -1
- package/build-module/tooltip/index.js +2 -2
- package/build-module/tooltip/index.js.map +1 -1
- package/build-style/style-rtl.css +1 -1
- package/build-style/style.css +1 -1
- package/build-types/autocomplete/index.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/private-apis.d.ts.map +1 -1
- package/build-types/tooltip/index.d.ts.map +1 -1
- package/package.json +21 -20
- package/src/autocomplete/index.tsx +136 -77
- 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/input-control/styles/input-control-styles.tsx +2 -2
- package/src/mobile/global-styles-context/utils.native.js +2 -2
- package/src/private-apis.ts +16 -0
- package/src/select-control/styles/select-control-styles.ts +2 -2
- package/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx +1 -1
- package/src/tabs/index.tsx +3 -3
- package/src/tabs/test/index.tsx +12 -3
- package/src/toggle-group-control/test/__snapshots__/index.tsx.snap +8 -0
- package/src/tooltip/index.tsx +2 -3
- package/tsconfig.tsbuildinfo +1 -1
package/build/tabs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Ariakit","_interopRequireWildcard","require","_compose","_element","_context","_tab","_tablist","_tabpanel","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","Tabs","selectOnMove","initialTabId","orientation","onSelect","children","selectedTabId","instanceId","useInstanceId","store","useTabStore","defaultSelectedId","setSelectedId","selectedId","strippedDownId","replace","isControlled","undefined","items","useState","tabsHavePopulated","useRef","length","current","selectedTab","find","item","id","firstEnabledTab","dimmed","initialTab","useLayoutEffect","
|
|
1
|
+
{"version":3,"names":["Ariakit","_interopRequireWildcard","require","_compose","_element","_context","_tab","_tablist","_tabpanel","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","Tabs","selectOnMove","initialTabId","orientation","onSelect","children","selectedTabId","instanceId","useInstanceId","store","useTabStore","defaultSelectedId","setSelectedId","selectedId","strippedDownId","replace","isControlled","undefined","items","useState","tabsHavePopulated","useRef","length","current","selectedTab","find","item","id","firstEnabledTab","dimmed","initialTab","useLayoutEffect","_react","createElement","TabsContext","Provider","value","TabList","Tab","TabPanel","_default","exports"],"sources":["@wordpress/components/src/tabs/index.tsx"],"sourcesContent":["/**\n * External dependencies\n */\n// eslint-disable-next-line no-restricted-imports\nimport * as Ariakit from '@ariakit/react';\n\n/**\n * WordPress dependencies\n */\nimport { useInstanceId } from '@wordpress/compose';\nimport { useLayoutEffect, useRef } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport type { TabsProps } from './types';\nimport { TabsContext } from './context';\nimport { Tab } from './tab';\nimport { TabList } from './tablist';\nimport { TabPanel } from './tabpanel';\n\nfunction Tabs( {\n\tselectOnMove = true,\n\tinitialTabId,\n\torientation = 'horizontal',\n\tonSelect,\n\tchildren,\n\tselectedTabId,\n}: TabsProps ) {\n\tconst instanceId = useInstanceId( Tabs, 'tabs' );\n\tconst store = Ariakit.useTabStore( {\n\t\tselectOnMove,\n\t\torientation,\n\t\tdefaultSelectedId: initialTabId && `${ instanceId }-${ initialTabId }`,\n\t\tsetSelectedId: ( selectedId ) => {\n\t\t\tconst strippedDownId =\n\t\t\t\ttypeof selectedId === 'string'\n\t\t\t\t\t? selectedId.replace( `${ instanceId }-`, '' )\n\t\t\t\t\t: selectedId;\n\t\t\tonSelect?.( strippedDownId );\n\t\t},\n\t\tselectedId: selectedTabId && `${ instanceId }-${ selectedTabId }`,\n\t} );\n\n\tconst isControlled = selectedTabId !== undefined;\n\n\tconst { items, selectedId } = store.useState();\n\tconst { setSelectedId } = store;\n\n\t// Keep track of whether tabs have been populated. This is used to prevent\n\t// certain effects from firing too early while tab data and relevant\n\t// variables are undefined during the initial render.\n\tconst tabsHavePopulated = useRef( false );\n\tif ( items.length > 0 ) {\n\t\ttabsHavePopulated.current = true;\n\t}\n\n\tconst selectedTab = items.find( ( item ) => item.id === selectedId );\n\tconst firstEnabledTab = items.find( ( item ) => {\n\t\t// Ariakit internally refers to disabled tabs as `dimmed`.\n\t\treturn ! item.dimmed;\n\t} );\n\tconst initialTab = items.find(\n\t\t( item ) => item.id === `${ instanceId }-${ initialTabId }`\n\t);\n\n\t// Handle selecting the initial tab.\n\tuseLayoutEffect( () => {\n\t\tif ( isControlled ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Wait for the denoted initial tab to be declared before making a\n\t\t// selection. This ensures that if a tab is declared lazily it can\n\t\t// still receive initial selection, as well as ensuring no tab is\n\t\t// selected if an invalid `initialTabId` is provided.\n\t\tif ( initialTabId && ! initialTab ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If the currently selected tab is missing (i.e. removed from the DOM),\n\t\t// fall back to the initial tab or the first enabled tab if there is\n\t\t// one. Otherwise, no tab should be selected.\n\t\tif ( ! items.find( ( item ) => item.id === selectedId ) ) {\n\t\t\tif ( initialTab && ! initialTab.dimmed ) {\n\t\t\t\tsetSelectedId( initialTab?.id );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( firstEnabledTab ) {\n\t\t\t\tsetSelectedId( firstEnabledTab.id );\n\t\t\t} else if ( tabsHavePopulated.current ) {\n\t\t\t\tsetSelectedId( null );\n\t\t\t}\n\t\t}\n\t}, [\n\t\tfirstEnabledTab,\n\t\tinitialTab,\n\t\tinitialTabId,\n\t\tisControlled,\n\t\titems,\n\t\tselectedId,\n\t\tsetSelectedId,\n\t] );\n\n\t// Handle the currently selected tab becoming disabled.\n\tuseLayoutEffect( () => {\n\t\tif ( ! selectedTab?.dimmed ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// In controlled mode, we trust that disabling tabs is done\n\t\t// intentionally, and don't select a new tab automatically.\n\t\tif ( isControlled ) {\n\t\t\tsetSelectedId( null );\n\t\t\treturn;\n\t\t}\n\n\t\t// If the currently selected tab becomes disabled, fall back to the\n\t\t// `initialTabId` if possible. Otherwise select the first\n\t\t// enabled tab (if there is one).\n\t\tif ( initialTab && ! initialTab.dimmed ) {\n\t\t\tsetSelectedId( initialTab.id );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( firstEnabledTab ) {\n\t\t\tsetSelectedId( firstEnabledTab.id );\n\t\t}\n\t}, [\n\t\tfirstEnabledTab,\n\t\tinitialTab,\n\t\tisControlled,\n\t\tselectedTab?.dimmed,\n\t\tsetSelectedId,\n\t] );\n\n\t// Clear `selectedId` if the active tab is removed from the DOM in controlled mode.\n\tuseLayoutEffect( () => {\n\t\tif ( ! isControlled ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once the tabs have populated, if the `selectedTabId` still can't be\n\t\t// found, clear the selection.\n\t\tif ( tabsHavePopulated.current && !! selectedTabId && ! selectedTab ) {\n\t\t\tsetSelectedId( null );\n\t\t}\n\t}, [\n\t\tisControlled,\n\t\tselectedId,\n\t\tselectedTab,\n\t\tselectedTabId,\n\t\tsetSelectedId,\n\t] );\n\n\treturn (\n\t\t<TabsContext.Provider value={ { store, instanceId } }>\n\t\t\t{ children }\n\t\t</TabsContext.Provider>\n\t);\n}\n\nTabs.TabList = TabList;\nTabs.Tab = Tab;\nTabs.TabPanel = TabPanel;\nexport default Tabs;\n"],"mappings":";;;;;;;AAIA,IAAAA,OAAA,GAAAC,uBAAA,CAAAC,OAAA;AAKA,IAAAC,QAAA,GAAAD,OAAA;AACA,IAAAE,QAAA,GAAAF,OAAA;AAMA,IAAAG,QAAA,GAAAH,OAAA;AACA,IAAAI,IAAA,GAAAJ,OAAA;AACA,IAAAK,QAAA,GAAAL,OAAA;AACA,IAAAM,SAAA,GAAAN,OAAA;AAAsC,SAAAO,yBAAAC,WAAA,eAAAC,OAAA,kCAAAC,iBAAA,OAAAD,OAAA,QAAAE,gBAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,WAAA,WAAAA,WAAA,GAAAG,gBAAA,GAAAD,iBAAA,KAAAF,WAAA;AAAA,SAAAT,wBAAAa,GAAA,EAAAJ,WAAA,SAAAA,WAAA,IAAAI,GAAA,IAAAA,GAAA,CAAAC,UAAA,WAAAD,GAAA,QAAAA,GAAA,oBAAAA,GAAA,wBAAAA,GAAA,4BAAAE,OAAA,EAAAF,GAAA,UAAAG,KAAA,GAAAR,wBAAA,CAAAC,WAAA,OAAAO,KAAA,IAAAA,KAAA,CAAAC,GAAA,CAAAJ,GAAA,YAAAG,KAAA,CAAAE,GAAA,CAAAL,GAAA,SAAAM,MAAA,WAAAC,qBAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,GAAA,IAAAX,GAAA,QAAAW,GAAA,kBAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAd,GAAA,EAAAW,GAAA,SAAAI,IAAA,GAAAR,qBAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAV,GAAA,EAAAW,GAAA,cAAAI,IAAA,KAAAA,IAAA,CAAAV,GAAA,IAAAU,IAAA,CAAAC,GAAA,KAAAR,MAAA,CAAAC,cAAA,CAAAH,MAAA,EAAAK,GAAA,EAAAI,IAAA,YAAAT,MAAA,CAAAK,GAAA,IAAAX,GAAA,CAAAW,GAAA,SAAAL,MAAA,CAAAJ,OAAA,GAAAF,GAAA,MAAAG,KAAA,IAAAA,KAAA,CAAAa,GAAA,CAAAhB,GAAA,EAAAM,MAAA,YAAAA,MAAA;AAnBtC;AACA;AACA;AACA;;AAGA;AACA;AACA;;AAaA,SAASW,IAAIA,CAAE;EACdC,YAAY,GAAG,IAAI;EACnBC,YAAY;EACZC,WAAW,GAAG,YAAY;EAC1BC,QAAQ;EACRC,QAAQ;EACRC;AACU,CAAC,EAAG;EACd,MAAMC,UAAU,GAAG,IAAAC,sBAAa,EAAER,IAAI,EAAE,MAAO,CAAC;EAChD,MAAMS,KAAK,GAAGxC,OAAO,CAACyC,WAAW,CAAE;IAClCT,YAAY;IACZE,WAAW;IACXQ,iBAAiB,EAAET,YAAY,IAAK,GAAGK,UAAY,IAAIL,YAAc,EAAC;IACtEU,aAAa,EAAIC,UAAU,IAAM;MAChC,MAAMC,cAAc,GACnB,OAAOD,UAAU,KAAK,QAAQ,GAC3BA,UAAU,CAACE,OAAO,CAAG,GAAGR,UAAY,GAAE,EAAE,EAAG,CAAC,GAC5CM,UAAU;MACdT,QAAQ,GAAIU,cAAe,CAAC;IAC7B,CAAC;IACDD,UAAU,EAAEP,aAAa,IAAK,GAAGC,UAAY,IAAID,aAAe;EACjE,CAAE,CAAC;EAEH,MAAMU,YAAY,GAAGV,aAAa,KAAKW,SAAS;EAEhD,MAAM;IAAEC,KAAK;IAAEL;EAAW,CAAC,GAAGJ,KAAK,CAACU,QAAQ,CAAC,CAAC;EAC9C,MAAM;IAAEP;EAAc,CAAC,GAAGH,KAAK;;EAE/B;EACA;EACA;EACA,MAAMW,iBAAiB,GAAG,IAAAC,eAAM,EAAE,KAAM,CAAC;EACzC,IAAKH,KAAK,CAACI,MAAM,GAAG,CAAC,EAAG;IACvBF,iBAAiB,CAACG,OAAO,GAAG,IAAI;EACjC;EAEA,MAAMC,WAAW,GAAGN,KAAK,CAACO,IAAI,CAAIC,IAAI,IAAMA,IAAI,CAACC,EAAE,KAAKd,UAAW,CAAC;EACpE,MAAMe,eAAe,GAAGV,KAAK,CAACO,IAAI,CAAIC,IAAI,IAAM;IAC/C;IACA,OAAO,CAAEA,IAAI,CAACG,MAAM;EACrB,CAAE,CAAC;EACH,MAAMC,UAAU,GAAGZ,KAAK,CAACO,IAAI,CAC1BC,IAAI,IAAMA,IAAI,CAACC,EAAE,KAAM,GAAGpB,UAAY,IAAIL,YAAc,EAC3D,CAAC;;EAED;EACA,IAAA6B,wBAAe,EAAE,MAAM;IACtB,IAAKf,YAAY,EAAG;MACnB;IACD;;IAEA;IACA;IACA;IACA;IACA,IAAKd,YAAY,IAAI,CAAE4B,UAAU,EAAG;MACnC;IACD;;IAEA;IACA;IACA;IACA,IAAK,CAAEZ,KAAK,CAACO,IAAI,CAAIC,IAAI,IAAMA,IAAI,CAACC,EAAE,KAAKd,UAAW,CAAC,EAAG;MACzD,IAAKiB,UAAU,IAAI,CAAEA,UAAU,CAACD,MAAM,EAAG;QACxCjB,aAAa,CAAEkB,UAAU,EAAEH,EAAG,CAAC;QAC/B;MACD;MAEA,IAAKC,eAAe,EAAG;QACtBhB,aAAa,CAAEgB,eAAe,CAACD,EAAG,CAAC;MACpC,CAAC,MAAM,IAAKP,iBAAiB,CAACG,OAAO,EAAG;QACvCX,aAAa,CAAE,IAAK,CAAC;MACtB;IACD;EACD,CAAC,EAAE,CACFgB,eAAe,EACfE,UAAU,EACV5B,YAAY,EACZc,YAAY,EACZE,KAAK,EACLL,UAAU,EACVD,aAAa,CACZ,CAAC;;EAEH;EACA,IAAAmB,wBAAe,EAAE,MAAM;IACtB,IAAK,CAAEP,WAAW,EAAEK,MAAM,EAAG;MAC5B;IACD;;IAEA;IACA;IACA,IAAKb,YAAY,EAAG;MACnBJ,aAAa,CAAE,IAAK,CAAC;MACrB;IACD;;IAEA;IACA;IACA;IACA,IAAKkB,UAAU,IAAI,CAAEA,UAAU,CAACD,MAAM,EAAG;MACxCjB,aAAa,CAAEkB,UAAU,CAACH,EAAG,CAAC;MAC9B;IACD;IAEA,IAAKC,eAAe,EAAG;MACtBhB,aAAa,CAAEgB,eAAe,CAACD,EAAG,CAAC;IACpC;EACD,CAAC,EAAE,CACFC,eAAe,EACfE,UAAU,EACVd,YAAY,EACZQ,WAAW,EAAEK,MAAM,EACnBjB,aAAa,CACZ,CAAC;;EAEH;EACA,IAAAmB,wBAAe,EAAE,MAAM;IACtB,IAAK,CAAEf,YAAY,EAAG;MACrB;IACD;;IAEA;IACA;IACA,IAAKI,iBAAiB,CAACG,OAAO,IAAI,CAAC,CAAEjB,aAAa,IAAI,CAAEkB,WAAW,EAAG;MACrEZ,aAAa,CAAE,IAAK,CAAC;IACtB;EACD,CAAC,EAAE,CACFI,YAAY,EACZH,UAAU,EACVW,WAAW,EACXlB,aAAa,EACbM,aAAa,CACZ,CAAC;EAEH,OACC,IAAAoB,MAAA,CAAAC,aAAA,EAAC3D,QAAA,CAAA4D,WAAW,CAACC,QAAQ;IAACC,KAAK,EAAG;MAAE3B,KAAK;MAAEF;IAAW;EAAG,GAClDF,QACmB,CAAC;AAEzB;AAEAL,IAAI,CAACqC,OAAO,GAAGA,gBAAO;AACtBrC,IAAI,CAACsC,GAAG,GAAGA,QAAG;AACdtC,IAAI,CAACuC,QAAQ,GAAGA,kBAAQ;AAAC,IAAAC,QAAA,GACVxC,IAAI;AAAAyC,OAAA,CAAAxD,OAAA,GAAAuD,QAAA"}
|
package/build/tooltip/index.js
CHANGED
|
@@ -68,12 +68,12 @@ function Tooltip(props) {
|
|
|
68
68
|
placement: computedPlacement,
|
|
69
69
|
timeout: delay
|
|
70
70
|
});
|
|
71
|
-
const isTooltipOpen = tooltipStore.useState('open');
|
|
72
71
|
return (0, _react.createElement)(_react.Fragment, null, (0, _react.createElement)(Ariakit.TooltipAnchor, {
|
|
73
72
|
onClick: hideOnClick ? tooltipStore.hide : undefined,
|
|
74
73
|
store: tooltipStore,
|
|
75
74
|
render: isOnlyChild ? children : undefined
|
|
76
|
-
}, isOnlyChild ? undefined : children), isOnlyChild && (text || shortcut) &&
|
|
75
|
+
}, isOnlyChild ? undefined : children), isOnlyChild && (text || shortcut) && (0, _react.createElement)(Ariakit.Tooltip, {
|
|
76
|
+
unmountOnHide: true,
|
|
77
77
|
className: "components-tooltip",
|
|
78
78
|
gutter: 4,
|
|
79
79
|
id: describedById,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Ariakit","_interopRequireWildcard","require","_compose","_element","_deprecated","_interopRequireDefault","_shortcut","_utils","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","TOOLTIP_DELAY","exports","Tooltip","props","children","delay","hideOnClick","placement","position","shortcut","text","baseId","useInstanceId","describedById","undefined","isOnlyChild","Children","count","process","env","NODE_ENV","console","error","computedPlacement","positionToPlacement","deprecated","since","alternative","tooltipStore","useTooltipStore","timeout","
|
|
1
|
+
{"version":3,"names":["Ariakit","_interopRequireWildcard","require","_compose","_element","_deprecated","_interopRequireDefault","_shortcut","_utils","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","TOOLTIP_DELAY","exports","Tooltip","props","children","delay","hideOnClick","placement","position","shortcut","text","baseId","useInstanceId","describedById","undefined","isOnlyChild","Children","count","process","env","NODE_ENV","console","error","computedPlacement","positionToPlacement","deprecated","since","alternative","tooltipStore","useTooltipStore","timeout","_react","createElement","Fragment","TooltipAnchor","onClick","hide","store","render","unmountOnHide","className","gutter","id","overflowPadding","_default"],"sources":["@wordpress/components/src/tooltip/index.tsx"],"sourcesContent":["/**\n * External dependencies\n */\n// eslint-disable-next-line no-restricted-imports\nimport * as Ariakit from '@ariakit/react';\n\n/**\n * WordPress dependencies\n */\nimport { useInstanceId } from '@wordpress/compose';\nimport { Children } from '@wordpress/element';\nimport deprecated from '@wordpress/deprecated';\n\n/**\n * Internal dependencies\n */\nimport type { TooltipProps } from './types';\nimport Shortcut from '../shortcut';\nimport { positionToPlacement } from '../popover/utils';\n\n/**\n * Time over anchor to wait before showing tooltip\n */\nexport const TOOLTIP_DELAY = 700;\n\nfunction Tooltip( props: TooltipProps ) {\n\tconst {\n\t\tchildren,\n\t\tdelay = TOOLTIP_DELAY,\n\t\thideOnClick = true,\n\t\tplacement,\n\t\tposition,\n\t\tshortcut,\n\t\ttext,\n\t} = props;\n\n\tconst baseId = useInstanceId( Tooltip, 'tooltip' );\n\tconst describedById = text || shortcut ? baseId : undefined;\n\n\tconst isOnlyChild = Children.count( children ) === 1;\n\t// console error if more than one child element is added\n\tif ( ! isOnlyChild ) {\n\t\tif ( 'development' === process.env.NODE_ENV ) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.error(\n\t\t\t\t'Tooltip should be called with only a single child element.'\n\t\t\t);\n\t\t}\n\t}\n\n\t// Compute tooltip's placement:\n\t// - give priority to `placement` prop, if defined\n\t// - otherwise, compute it from the legacy `position` prop (if defined)\n\t// - finally, fallback to the default placement: 'bottom'\n\tlet computedPlacement;\n\tif ( placement !== undefined ) {\n\t\tcomputedPlacement = placement;\n\t} else if ( position !== undefined ) {\n\t\tcomputedPlacement = positionToPlacement( position );\n\t\tdeprecated( '`position` prop in wp.components.tooltip', {\n\t\t\tsince: '6.4',\n\t\t\talternative: '`placement` prop',\n\t\t} );\n\t}\n\tcomputedPlacement = computedPlacement || 'bottom';\n\n\tconst tooltipStore = Ariakit.useTooltipStore( {\n\t\tplacement: computedPlacement,\n\t\ttimeout: delay,\n\t} );\n\n\treturn (\n\t\t<>\n\t\t\t<Ariakit.TooltipAnchor\n\t\t\t\tonClick={ hideOnClick ? tooltipStore.hide : undefined }\n\t\t\t\tstore={ tooltipStore }\n\t\t\t\trender={ isOnlyChild ? children : undefined }\n\t\t\t>\n\t\t\t\t{ isOnlyChild ? undefined : children }\n\t\t\t</Ariakit.TooltipAnchor>\n\t\t\t{ isOnlyChild && ( text || shortcut ) && (\n\t\t\t\t<Ariakit.Tooltip\n\t\t\t\t\tunmountOnHide\n\t\t\t\t\tclassName=\"components-tooltip\"\n\t\t\t\t\tgutter={ 4 }\n\t\t\t\t\tid={ describedById }\n\t\t\t\t\toverflowPadding={ 0.5 }\n\t\t\t\t\tstore={ tooltipStore }\n\t\t\t\t>\n\t\t\t\t\t{ text }\n\t\t\t\t\t{ shortcut && (\n\t\t\t\t\t\t<Shortcut\n\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\ttext ? 'components-tooltip__shortcut' : ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tshortcut={ shortcut }\n\t\t\t\t\t\t/>\n\t\t\t\t\t) }\n\t\t\t\t</Ariakit.Tooltip>\n\t\t\t) }\n\t\t</>\n\t);\n}\n\nexport default Tooltip;\n"],"mappings":"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"}
|
|
@@ -10,12 +10,41 @@ import removeAccents from 'remove-accents';
|
|
|
10
10
|
import { renderToString, useEffect, useState, useRef, useMemo } from '@wordpress/element';
|
|
11
11
|
import { useInstanceId, useMergeRefs, useRefEffect } from '@wordpress/compose';
|
|
12
12
|
import { create, slice, insert, isCollapsed, getTextContent } from '@wordpress/rich-text';
|
|
13
|
+
import { speak } from '@wordpress/a11y';
|
|
14
|
+
import { isAppleOS } from '@wordpress/keycodes';
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* Internal dependencies
|
|
16
18
|
*/
|
|
17
19
|
import { getAutoCompleterUI } from './autocompleter-ui';
|
|
18
20
|
import { escapeRegExp } from '../utils/strings';
|
|
21
|
+
const getNodeText = node => {
|
|
22
|
+
if (node === null) {
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
switch (typeof node) {
|
|
26
|
+
case 'string':
|
|
27
|
+
case 'number':
|
|
28
|
+
return node.toString();
|
|
29
|
+
break;
|
|
30
|
+
case 'boolean':
|
|
31
|
+
return '';
|
|
32
|
+
break;
|
|
33
|
+
case 'object':
|
|
34
|
+
{
|
|
35
|
+
if (node instanceof Array) {
|
|
36
|
+
return node.map(getNodeText).join('');
|
|
37
|
+
}
|
|
38
|
+
if ('props' in node) {
|
|
39
|
+
return getNodeText(node.props.children);
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
default:
|
|
44
|
+
return '';
|
|
45
|
+
}
|
|
46
|
+
return '';
|
|
47
|
+
};
|
|
19
48
|
const EMPTY_FILTERED_OPTIONS = [];
|
|
20
49
|
export function useAutocomplete({
|
|
21
50
|
record,
|
|
@@ -108,11 +137,24 @@ export function useAutocomplete({
|
|
|
108
137
|
}
|
|
109
138
|
switch (event.key) {
|
|
110
139
|
case 'ArrowUp':
|
|
111
|
-
|
|
112
|
-
|
|
140
|
+
{
|
|
141
|
+
const newIndex = (selectedIndex === 0 ? filteredOptions.length : selectedIndex) - 1;
|
|
142
|
+
setSelectedIndex(newIndex);
|
|
143
|
+
// See the related PR as to why this is necessary: https://github.com/WordPress/gutenberg/pull/54902.
|
|
144
|
+
if (isAppleOS()) {
|
|
145
|
+
speak(getNodeText(filteredOptions[newIndex].label), 'assertive');
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
113
149
|
case 'ArrowDown':
|
|
114
|
-
|
|
115
|
-
|
|
150
|
+
{
|
|
151
|
+
const newIndex = (selectedIndex + 1) % filteredOptions.length;
|
|
152
|
+
setSelectedIndex(newIndex);
|
|
153
|
+
if (isAppleOS()) {
|
|
154
|
+
speak(getNodeText(filteredOptions[newIndex].label), 'assertive');
|
|
155
|
+
}
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
116
158
|
case 'Escape':
|
|
117
159
|
setAutocompleter(null);
|
|
118
160
|
setAutocompleterUI(null);
|
|
@@ -148,58 +190,68 @@ export function useAutocomplete({
|
|
|
148
190
|
if (autocompleter) reset();
|
|
149
191
|
return;
|
|
150
192
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const textWithoutTrigger = textContent.slice(index + triggerPrefix.length);
|
|
160
|
-
const tooDistantFromTrigger = textWithoutTrigger.length > 50; // 50 chars seems to be a good limit.
|
|
161
|
-
// This is a final barrier to prevent the effect from completing with
|
|
162
|
-
// an extremely long string, which causes the editor to slow-down
|
|
163
|
-
// significantly. This could happen, for example, if `matchingWhileBackspacing`
|
|
164
|
-
// is true and one of the "words" end up being too long. If that's the case,
|
|
165
|
-
// it will be caught by this guard.
|
|
166
|
-
if (tooDistantFromTrigger) return false;
|
|
167
|
-
const mismatch = filteredOptions.length === 0;
|
|
168
|
-
const wordsFromTrigger = textWithoutTrigger.split(/\s/);
|
|
169
|
-
// We need to allow the effect to run when not backspacing and if there
|
|
170
|
-
// was a mismatch. i.e when typing a trigger + the match string or when
|
|
171
|
-
// clicking in an existing trigger word on the page. We do that if we
|
|
172
|
-
// detect that we have one word from trigger in the current textual context.
|
|
173
|
-
//
|
|
174
|
-
// Ex.: "Some text @a" <-- "@a" will be detected as the trigger word and
|
|
175
|
-
// allow the effect to run. It will run until there's a mismatch.
|
|
176
|
-
const hasOneTriggerWord = wordsFromTrigger.length === 1;
|
|
177
|
-
// This is used to allow the effect to run when backspacing and if
|
|
178
|
-
// "touching" a word that "belongs" to a trigger. We consider a "trigger
|
|
179
|
-
// word" any word up to the limit of 3 from the trigger character.
|
|
180
|
-
// Anything beyond that is ignored if there's a mismatch. This allows
|
|
181
|
-
// us to "escape" a mismatch when backspacing, but still imposing some
|
|
182
|
-
// sane limits.
|
|
183
|
-
//
|
|
184
|
-
// Ex: "Some text @marcelo sekkkk" <--- "kkkk" caused a mismatch, but
|
|
185
|
-
// if the user presses backspace here, it will show the completion popup again.
|
|
186
|
-
const matchingWhileBackspacing = backspacing.current && textWithoutTrigger.split(/\s/).length <= 3;
|
|
187
|
-
if (mismatch && !(matchingWhileBackspacing || hasOneTriggerWord)) {
|
|
188
|
-
return false;
|
|
189
|
-
}
|
|
190
|
-
const textAfterSelection = getTextContent(slice(record, undefined, getTextContent(record).length));
|
|
191
|
-
if (allowContext && !allowContext(textContent.slice(0, index), textAfterSelection)) {
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
if (/^\s/.test(textWithoutTrigger) || /\s\s+$/.test(textWithoutTrigger)) {
|
|
195
|
-
return false;
|
|
196
|
-
}
|
|
197
|
-
return /[\u0000-\uFFFF]*$/.test(textWithoutTrigger);
|
|
198
|
-
});
|
|
193
|
+
|
|
194
|
+
// Find the completer with the highest triggerPrefix index in the
|
|
195
|
+
// textContent.
|
|
196
|
+
const completer = completers.reduce((lastTrigger, currentCompleter) => {
|
|
197
|
+
const triggerIndex = textContent.lastIndexOf(currentCompleter.triggerPrefix);
|
|
198
|
+
const lastTriggerIndex = lastTrigger !== null ? textContent.lastIndexOf(lastTrigger.triggerPrefix) : -1;
|
|
199
|
+
return triggerIndex > lastTriggerIndex ? currentCompleter : lastTrigger;
|
|
200
|
+
}, null);
|
|
199
201
|
if (!completer) {
|
|
200
202
|
if (autocompleter) reset();
|
|
201
203
|
return;
|
|
202
204
|
}
|
|
205
|
+
const {
|
|
206
|
+
allowContext,
|
|
207
|
+
triggerPrefix
|
|
208
|
+
} = completer;
|
|
209
|
+
const triggerIndex = textContent.lastIndexOf(triggerPrefix);
|
|
210
|
+
const textWithoutTrigger = textContent.slice(triggerIndex + triggerPrefix.length);
|
|
211
|
+
const tooDistantFromTrigger = textWithoutTrigger.length > 50; // 50 chars seems to be a good limit.
|
|
212
|
+
// This is a final barrier to prevent the effect from completing with
|
|
213
|
+
// an extremely long string, which causes the editor to slow-down
|
|
214
|
+
// significantly. This could happen, for example, if `matchingWhileBackspacing`
|
|
215
|
+
// is true and one of the "words" end up being too long. If that's the case,
|
|
216
|
+
// it will be caught by this guard.
|
|
217
|
+
if (tooDistantFromTrigger) return;
|
|
218
|
+
const mismatch = filteredOptions.length === 0;
|
|
219
|
+
const wordsFromTrigger = textWithoutTrigger.split(/\s/);
|
|
220
|
+
// We need to allow the effect to run when not backspacing and if there
|
|
221
|
+
// was a mismatch. i.e when typing a trigger + the match string or when
|
|
222
|
+
// clicking in an existing trigger word on the page. We do that if we
|
|
223
|
+
// detect that we have one word from trigger in the current textual context.
|
|
224
|
+
//
|
|
225
|
+
// Ex.: "Some text @a" <-- "@a" will be detected as the trigger word and
|
|
226
|
+
// allow the effect to run. It will run until there's a mismatch.
|
|
227
|
+
const hasOneTriggerWord = wordsFromTrigger.length === 1;
|
|
228
|
+
// This is used to allow the effect to run when backspacing and if
|
|
229
|
+
// "touching" a word that "belongs" to a trigger. We consider a "trigger
|
|
230
|
+
// word" any word up to the limit of 3 from the trigger character.
|
|
231
|
+
// Anything beyond that is ignored if there's a mismatch. This allows
|
|
232
|
+
// us to "escape" a mismatch when backspacing, but still imposing some
|
|
233
|
+
// sane limits.
|
|
234
|
+
//
|
|
235
|
+
// Ex: "Some text @marcelo sekkkk" <--- "kkkk" caused a mismatch, but
|
|
236
|
+
// if the user presses backspace here, it will show the completion popup again.
|
|
237
|
+
const matchingWhileBackspacing = backspacing.current && wordsFromTrigger.length <= 3;
|
|
238
|
+
if (mismatch && !(matchingWhileBackspacing || hasOneTriggerWord)) {
|
|
239
|
+
if (autocompleter) reset();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const textAfterSelection = getTextContent(slice(record, undefined, getTextContent(record).length));
|
|
243
|
+
if (allowContext && !allowContext(textContent.slice(0, triggerIndex), textAfterSelection)) {
|
|
244
|
+
if (autocompleter) reset();
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (/^\s/.test(textWithoutTrigger) || /\s\s+$/.test(textWithoutTrigger)) {
|
|
248
|
+
if (autocompleter) reset();
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (!/[\u0000-\uFFFF]*$/.test(textWithoutTrigger)) {
|
|
252
|
+
if (autocompleter) reset();
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
203
255
|
const safeTrigger = escapeRegExp(completer.triggerPrefix);
|
|
204
256
|
const text = removeAccents(textContent);
|
|
205
257
|
const match = text.slice(text.lastIndexOf(completer.triggerPrefix)).match(new RegExp(`${safeTrigger}([\u0000-\uFFFF]*)$`));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["removeAccents","renderToString","useEffect","useState","useRef","useMemo","useInstanceId","useMergeRefs","useRefEffect","create","slice","insert","isCollapsed","getTextContent","getAutoCompleterUI","escapeRegExp","EMPTY_FILTERED_OPTIONS","useAutocomplete","record","onChange","onReplace","completers","contentRef","instanceId","selectedIndex","setSelectedIndex","filteredOptions","setFilteredOptions","filterValue","setFilterValue","autocompleter","setAutocompleter","AutocompleterUI","setAutocompleterUI","backspacing","insertCompletion","replacement","end","start","triggerPrefix","length","toInsert","html","select","option","getOptionCompletion","isDisabled","completion","value","isCompletionObject","obj","action","undefined","completionObject","reset","onChangeOptions","options","handleKeyDown","event","current","key","defaultPrevented","isComposing","keyCode","preventDefault","textContent","completer","find","allowContext","index","lastIndexOf","textWithoutTrigger","tooDistantFromTrigger","mismatch","wordsFromTrigger","split","hasOneTriggerWord","matchingWhileBackspacing","textAfterSelection","test","safeTrigger","text","match","RegExp","query","selectedKey","className","isExpanded","listBoxId","activeId","hasSelection","onKeyDown","popover","createElement","onSelect","useLastDifferentValue","history","Set","add","size","delete","Array","from","useAutocompleteProps","ref","onKeyDownRef","previousRecord","mergedRefs","element","_onKeyDown","addEventListener","removeEventListener","didUserInput","children","Autocomplete","isSelected","props","Fragment"],"sources":["@wordpress/components/src/autocomplete/index.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport removeAccents from 'remove-accents';\n\n/**\n * WordPress dependencies\n */\nimport {\n\trenderToString,\n\tuseEffect,\n\tuseState,\n\tuseRef,\n\tuseMemo,\n} from '@wordpress/element';\nimport { __, _n } from '@wordpress/i18n';\nimport { useInstanceId, useMergeRefs, useRefEffect } from '@wordpress/compose';\nimport {\n\tcreate,\n\tslice,\n\tinsert,\n\tisCollapsed,\n\tgetTextContent,\n} from '@wordpress/rich-text';\n\n/**\n * Internal dependencies\n */\nimport { getAutoCompleterUI } from './autocompleter-ui';\nimport { escapeRegExp } from '../utils/strings';\nimport type {\n\tAutocompleteProps,\n\tAutocompleterUIProps,\n\tInsertOption,\n\tKeyedOption,\n\tOptionCompletion,\n\tReplaceOption,\n\tUseAutocompleteProps,\n\tWPCompleter,\n} from './types';\n\nconst EMPTY_FILTERED_OPTIONS: KeyedOption[] = [];\n\nexport function useAutocomplete( {\n\trecord,\n\tonChange,\n\tonReplace,\n\tcompleters,\n\tcontentRef,\n}: UseAutocompleteProps ) {\n\tconst instanceId = useInstanceId( useAutocomplete );\n\tconst [ selectedIndex, setSelectedIndex ] = useState( 0 );\n\n\tconst [ filteredOptions, setFilteredOptions ] = useState<\n\t\tArray< KeyedOption >\n\t>( EMPTY_FILTERED_OPTIONS );\n\tconst [ filterValue, setFilterValue ] =\n\t\tuseState< AutocompleterUIProps[ 'filterValue' ] >( '' );\n\tconst [ autocompleter, setAutocompleter ] = useState< WPCompleter | null >(\n\t\tnull\n\t);\n\tconst [ AutocompleterUI, setAutocompleterUI ] = useState<\n\t\t( ( props: AutocompleterUIProps ) => JSX.Element | null ) | null\n\t>( null );\n\n\tconst backspacing = useRef( false );\n\n\tfunction insertCompletion( replacement: React.ReactNode ) {\n\t\tif ( autocompleter === null ) {\n\t\t\treturn;\n\t\t}\n\t\tconst end = record.start;\n\t\tconst start =\n\t\t\tend - autocompleter.triggerPrefix.length - filterValue.length;\n\t\tconst toInsert = create( { html: renderToString( replacement ) } );\n\n\t\tonChange( insert( record, toInsert, start, end ) );\n\t}\n\n\tfunction select( option: KeyedOption ) {\n\t\tconst { getOptionCompletion } = autocompleter || {};\n\n\t\tif ( option.isDisabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( getOptionCompletion ) {\n\t\t\tconst completion = getOptionCompletion( option.value, filterValue );\n\n\t\t\tconst isCompletionObject = (\n\t\t\t\tobj: OptionCompletion\n\t\t\t): obj is InsertOption | ReplaceOption => {\n\t\t\t\treturn (\n\t\t\t\t\tobj !== null &&\n\t\t\t\t\ttypeof obj === 'object' &&\n\t\t\t\t\t'action' in obj &&\n\t\t\t\t\tobj.action !== undefined &&\n\t\t\t\t\t'value' in obj &&\n\t\t\t\t\tobj.value !== undefined\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tconst completionObject = isCompletionObject( completion )\n\t\t\t\t? completion\n\t\t\t\t: ( {\n\t\t\t\t\t\taction: 'insert-at-caret',\n\t\t\t\t\t\tvalue: completion,\n\t\t\t\t } as InsertOption );\n\n\t\t\tif ( 'replace' === completionObject.action ) {\n\t\t\t\tonReplace( [ completionObject.value ] );\n\t\t\t\t// When replacing, the component will unmount, so don't reset\n\t\t\t\t// state (below) on an unmounted component.\n\t\t\t\treturn;\n\t\t\t} else if ( 'insert-at-caret' === completionObject.action ) {\n\t\t\t\tinsertCompletion( completionObject.value );\n\t\t\t}\n\t\t}\n\n\t\t// Reset autocomplete state after insertion rather than before\n\t\t// so insertion events don't cause the completion menu to redisplay.\n\t\treset();\n\t}\n\n\tfunction reset() {\n\t\tsetSelectedIndex( 0 );\n\t\tsetFilteredOptions( EMPTY_FILTERED_OPTIONS );\n\t\tsetFilterValue( '' );\n\t\tsetAutocompleter( null );\n\t\tsetAutocompleterUI( null );\n\t}\n\n\t/**\n\t * Load options for an autocompleter.\n\t *\n\t * @param {Array} options\n\t */\n\tfunction onChangeOptions( options: Array< KeyedOption > ) {\n\t\tsetSelectedIndex(\n\t\t\toptions.length === filteredOptions.length ? selectedIndex : 0\n\t\t);\n\t\tsetFilteredOptions( options );\n\t}\n\n\tfunction handleKeyDown( event: KeyboardEvent ) {\n\t\tbackspacing.current = event.key === 'Backspace';\n\n\t\tif ( ! autocompleter ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( filteredOptions.length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tevent.defaultPrevented ||\n\t\t\t// Ignore keydowns from IMEs\n\t\t\tevent.isComposing ||\n\t\t\t// Workaround for Mac Safari where the final Enter/Backspace of an IME composition\n\t\t\t// is `isComposing=false`, even though it's technically still part of the composition.\n\t\t\t// These can only be detected by keyCode.\n\t\t\tevent.keyCode === 229\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tswitch ( event.key ) {\n\t\t\tcase 'ArrowUp':\n\t\t\t\tsetSelectedIndex(\n\t\t\t\t\t( selectedIndex === 0\n\t\t\t\t\t\t? filteredOptions.length\n\t\t\t\t\t\t: selectedIndex ) - 1\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase 'ArrowDown':\n\t\t\t\tsetSelectedIndex(\n\t\t\t\t\t( selectedIndex + 1 ) % filteredOptions.length\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase 'Escape':\n\t\t\t\tsetAutocompleter( null );\n\t\t\t\tsetAutocompleterUI( null );\n\t\t\t\tevent.preventDefault();\n\t\t\t\tbreak;\n\n\t\t\tcase 'Enter':\n\t\t\t\tselect( filteredOptions[ selectedIndex ] );\n\t\t\t\tbreak;\n\n\t\t\tcase 'ArrowLeft':\n\t\t\tcase 'ArrowRight':\n\t\t\t\treset();\n\t\t\t\treturn;\n\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\t// Any handled key should prevent original behavior. This relies on\n\t\t// the early return in the default case.\n\t\tevent.preventDefault();\n\t}\n\n\t// textContent is a primitive (string), memoizing is not strictly necessary\n\t// but this is a preemptive performance improvement, since the autocompleter\n\t// is a potential bottleneck for the editor type metric.\n\tconst textContent = useMemo( () => {\n\t\tif ( isCollapsed( record ) ) {\n\t\t\treturn getTextContent( slice( record, 0 ) );\n\t\t}\n\t\treturn '';\n\t}, [ record ] );\n\n\tuseEffect( () => {\n\t\tif ( ! textContent ) {\n\t\t\tif ( autocompleter ) reset();\n\t\t\treturn;\n\t\t}\n\n\t\tconst completer = completers?.find(\n\t\t\t( { triggerPrefix, allowContext } ) => {\n\t\t\t\tconst index = textContent.lastIndexOf( triggerPrefix );\n\n\t\t\t\tif ( index === -1 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tconst textWithoutTrigger = textContent.slice(\n\t\t\t\t\tindex + triggerPrefix.length\n\t\t\t\t);\n\n\t\t\t\tconst tooDistantFromTrigger = textWithoutTrigger.length > 50; // 50 chars seems to be a good limit.\n\t\t\t\t// This is a final barrier to prevent the effect from completing with\n\t\t\t\t// an extremely long string, which causes the editor to slow-down\n\t\t\t\t// significantly. This could happen, for example, if `matchingWhileBackspacing`\n\t\t\t\t// is true and one of the \"words\" end up being too long. If that's the case,\n\t\t\t\t// it will be caught by this guard.\n\t\t\t\tif ( tooDistantFromTrigger ) return false;\n\n\t\t\t\tconst mismatch = filteredOptions.length === 0;\n\t\t\t\tconst wordsFromTrigger = textWithoutTrigger.split( /\\s/ );\n\t\t\t\t// We need to allow the effect to run when not backspacing and if there\n\t\t\t\t// was a mismatch. i.e when typing a trigger + the match string or when\n\t\t\t\t// clicking in an existing trigger word on the page. We do that if we\n\t\t\t\t// detect that we have one word from trigger in the current textual context.\n\t\t\t\t//\n\t\t\t\t// Ex.: \"Some text @a\" <-- \"@a\" will be detected as the trigger word and\n\t\t\t\t// allow the effect to run. It will run until there's a mismatch.\n\t\t\t\tconst hasOneTriggerWord = wordsFromTrigger.length === 1;\n\t\t\t\t// This is used to allow the effect to run when backspacing and if\n\t\t\t\t// \"touching\" a word that \"belongs\" to a trigger. We consider a \"trigger\n\t\t\t\t// word\" any word up to the limit of 3 from the trigger character.\n\t\t\t\t// Anything beyond that is ignored if there's a mismatch. This allows\n\t\t\t\t// us to \"escape\" a mismatch when backspacing, but still imposing some\n\t\t\t\t// sane limits.\n\t\t\t\t//\n\t\t\t\t// Ex: \"Some text @marcelo sekkkk\" <--- \"kkkk\" caused a mismatch, but\n\t\t\t\t// if the user presses backspace here, it will show the completion popup again.\n\t\t\t\tconst matchingWhileBackspacing =\n\t\t\t\t\tbackspacing.current &&\n\t\t\t\t\ttextWithoutTrigger.split( /\\s/ ).length <= 3;\n\n\t\t\t\tif (\n\t\t\t\t\tmismatch &&\n\t\t\t\t\t! ( matchingWhileBackspacing || hasOneTriggerWord )\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tconst textAfterSelection = getTextContent(\n\t\t\t\t\tslice( record, undefined, getTextContent( record ).length )\n\t\t\t\t);\n\n\t\t\t\tif (\n\t\t\t\t\tallowContext &&\n\t\t\t\t\t! allowContext(\n\t\t\t\t\t\ttextContent.slice( 0, index ),\n\t\t\t\t\t\ttextAfterSelection\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t/^\\s/.test( textWithoutTrigger ) ||\n\t\t\t\t\t/\\s\\s+$/.test( textWithoutTrigger )\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\treturn /[\\u0000-\\uFFFF]*$/.test( textWithoutTrigger );\n\t\t\t}\n\t\t);\n\n\t\tif ( ! completer ) {\n\t\t\tif ( autocompleter ) reset();\n\t\t\treturn;\n\t\t}\n\n\t\tconst safeTrigger = escapeRegExp( completer.triggerPrefix );\n\t\tconst text = removeAccents( textContent );\n\t\tconst match = text\n\t\t\t.slice( text.lastIndexOf( completer.triggerPrefix ) )\n\t\t\t.match( new RegExp( `${ safeTrigger }([\\u0000-\\uFFFF]*)$` ) );\n\t\tconst query = match && match[ 1 ];\n\n\t\tsetAutocompleter( completer );\n\t\tsetAutocompleterUI( () =>\n\t\t\tcompleter !== autocompleter\n\t\t\t\t? getAutoCompleterUI( completer )\n\t\t\t\t: AutocompleterUI\n\t\t);\n\t\tsetFilterValue( query === null ? '' : query );\n\t\t// Temporarily disabling exhaustive-deps to avoid introducing unexpected side effecst.\n\t\t// See https://github.com/WordPress/gutenberg/pull/41820\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [ textContent ] );\n\n\tconst { key: selectedKey = '' } = filteredOptions[ selectedIndex ] || {};\n\tconst { className } = autocompleter || {};\n\tconst isExpanded = !! autocompleter && filteredOptions.length > 0;\n\tconst listBoxId = isExpanded\n\t\t? `components-autocomplete-listbox-${ instanceId }`\n\t\t: undefined;\n\tconst activeId = isExpanded\n\t\t? `components-autocomplete-item-${ instanceId }-${ selectedKey }`\n\t\t: null;\n\tconst hasSelection = record.start !== undefined;\n\n\treturn {\n\t\tlistBoxId,\n\t\tactiveId,\n\t\tonKeyDown: handleKeyDown,\n\t\tpopover: hasSelection && AutocompleterUI && (\n\t\t\t<AutocompleterUI\n\t\t\t\tclassName={ className }\n\t\t\t\tfilterValue={ filterValue }\n\t\t\t\tinstanceId={ instanceId }\n\t\t\t\tlistBoxId={ listBoxId }\n\t\t\t\tselectedIndex={ selectedIndex }\n\t\t\t\tonChangeOptions={ onChangeOptions }\n\t\t\t\tonSelect={ select }\n\t\t\t\tvalue={ record }\n\t\t\t\tcontentRef={ contentRef }\n\t\t\t\treset={ reset }\n\t\t\t/>\n\t\t),\n\t};\n}\n\nfunction useLastDifferentValue( value: UseAutocompleteProps[ 'record' ] ) {\n\tconst history = useRef< Set< typeof value > >( new Set() );\n\n\thistory.current.add( value );\n\n\t// Keep the history size to 2.\n\tif ( history.current.size > 2 ) {\n\t\thistory.current.delete( Array.from( history.current )[ 0 ] );\n\t}\n\n\treturn Array.from( history.current )[ 0 ];\n}\n\nexport function useAutocompleteProps( options: UseAutocompleteProps ) {\n\tconst ref = useRef< HTMLElement >( null );\n\tconst onKeyDownRef = useRef< ( event: KeyboardEvent ) => void >();\n\tconst { record } = options;\n\tconst previousRecord = useLastDifferentValue( record );\n\tconst { popover, listBoxId, activeId, onKeyDown } = useAutocomplete( {\n\t\t...options,\n\t\tcontentRef: ref,\n\t} );\n\tonKeyDownRef.current = onKeyDown;\n\n\tconst mergedRefs = useMergeRefs( [\n\t\tref,\n\t\tuseRefEffect( ( element: HTMLElement ) => {\n\t\t\tfunction _onKeyDown( event: KeyboardEvent ) {\n\t\t\t\tonKeyDownRef.current?.( event );\n\t\t\t}\n\t\t\telement.addEventListener( 'keydown', _onKeyDown );\n\t\t\treturn () => {\n\t\t\t\telement.removeEventListener( 'keydown', _onKeyDown );\n\t\t\t};\n\t\t}, [] ),\n\t] );\n\n\t// We only want to show the popover if the user has typed something.\n\tconst didUserInput = record.text !== previousRecord?.text;\n\n\tif ( ! didUserInput ) {\n\t\treturn { ref: mergedRefs };\n\t}\n\n\treturn {\n\t\tref: mergedRefs,\n\t\tchildren: popover,\n\t\t'aria-autocomplete': listBoxId ? 'list' : undefined,\n\t\t'aria-owns': listBoxId,\n\t\t'aria-activedescendant': activeId,\n\t};\n}\n\nexport default function Autocomplete( {\n\tchildren,\n\tisSelected,\n\t...options\n}: AutocompleteProps ) {\n\tconst { popover, ...props } = useAutocomplete( options );\n\treturn (\n\t\t<>\n\t\t\t{ children( props ) }\n\t\t\t{ isSelected && popover }\n\t\t</>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["removeAccents","renderToString","useEffect","useState","useRef","useMemo","useInstanceId","useMergeRefs","useRefEffect","create","slice","insert","isCollapsed","getTextContent","speak","isAppleOS","getAutoCompleterUI","escapeRegExp","getNodeText","node","toString","Array","map","join","props","children","EMPTY_FILTERED_OPTIONS","useAutocomplete","record","onChange","onReplace","completers","contentRef","instanceId","selectedIndex","setSelectedIndex","filteredOptions","setFilteredOptions","filterValue","setFilterValue","autocompleter","setAutocompleter","AutocompleterUI","setAutocompleterUI","backspacing","insertCompletion","replacement","end","start","triggerPrefix","length","toInsert","html","select","option","getOptionCompletion","isDisabled","completion","value","isCompletionObject","obj","action","undefined","completionObject","reset","onChangeOptions","options","handleKeyDown","event","current","key","defaultPrevented","isComposing","keyCode","newIndex","label","preventDefault","textContent","completer","reduce","lastTrigger","currentCompleter","triggerIndex","lastIndexOf","lastTriggerIndex","allowContext","textWithoutTrigger","tooDistantFromTrigger","mismatch","wordsFromTrigger","split","hasOneTriggerWord","matchingWhileBackspacing","textAfterSelection","test","safeTrigger","text","match","RegExp","query","selectedKey","className","isExpanded","listBoxId","activeId","hasSelection","onKeyDown","popover","createElement","onSelect","useLastDifferentValue","history","Set","add","size","delete","from","useAutocompleteProps","ref","onKeyDownRef","previousRecord","mergedRefs","element","_onKeyDown","addEventListener","removeEventListener","didUserInput","Autocomplete","isSelected","Fragment"],"sources":["@wordpress/components/src/autocomplete/index.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport removeAccents from 'remove-accents';\n\n/**\n * WordPress dependencies\n */\nimport {\n\trenderToString,\n\tuseEffect,\n\tuseState,\n\tuseRef,\n\tuseMemo,\n} from '@wordpress/element';\nimport { __, _n } from '@wordpress/i18n';\nimport { useInstanceId, useMergeRefs, useRefEffect } from '@wordpress/compose';\nimport {\n\tcreate,\n\tslice,\n\tinsert,\n\tisCollapsed,\n\tgetTextContent,\n} from '@wordpress/rich-text';\nimport { speak } from '@wordpress/a11y';\nimport { isAppleOS } from '@wordpress/keycodes';\n\n/**\n * Internal dependencies\n */\nimport { getAutoCompleterUI } from './autocompleter-ui';\nimport { escapeRegExp } from '../utils/strings';\nimport type {\n\tAutocompleteProps,\n\tAutocompleterUIProps,\n\tInsertOption,\n\tKeyedOption,\n\tOptionCompletion,\n\tReplaceOption,\n\tUseAutocompleteProps,\n\tWPCompleter,\n} from './types';\n\nconst getNodeText = ( node: React.ReactNode ): string => {\n\tif ( node === null ) {\n\t\treturn '';\n\t}\n\n\tswitch ( typeof node ) {\n\t\tcase 'string':\n\t\tcase 'number':\n\t\t\treturn node.toString();\n\t\t\tbreak;\n\t\tcase 'boolean':\n\t\t\treturn '';\n\t\t\tbreak;\n\t\tcase 'object': {\n\t\t\tif ( node instanceof Array ) {\n\t\t\t\treturn node.map( getNodeText ).join( '' );\n\t\t\t}\n\t\t\tif ( 'props' in node ) {\n\t\t\t\treturn getNodeText( node.props.children );\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\treturn '';\n\t}\n\n\treturn '';\n};\n\nconst EMPTY_FILTERED_OPTIONS: KeyedOption[] = [];\n\nexport function useAutocomplete( {\n\trecord,\n\tonChange,\n\tonReplace,\n\tcompleters,\n\tcontentRef,\n}: UseAutocompleteProps ) {\n\tconst instanceId = useInstanceId( useAutocomplete );\n\tconst [ selectedIndex, setSelectedIndex ] = useState( 0 );\n\n\tconst [ filteredOptions, setFilteredOptions ] = useState<\n\t\tArray< KeyedOption >\n\t>( EMPTY_FILTERED_OPTIONS );\n\tconst [ filterValue, setFilterValue ] =\n\t\tuseState< AutocompleterUIProps[ 'filterValue' ] >( '' );\n\tconst [ autocompleter, setAutocompleter ] = useState< WPCompleter | null >(\n\t\tnull\n\t);\n\tconst [ AutocompleterUI, setAutocompleterUI ] = useState<\n\t\t( ( props: AutocompleterUIProps ) => JSX.Element | null ) | null\n\t>( null );\n\n\tconst backspacing = useRef( false );\n\n\tfunction insertCompletion( replacement: React.ReactNode ) {\n\t\tif ( autocompleter === null ) {\n\t\t\treturn;\n\t\t}\n\t\tconst end = record.start;\n\t\tconst start =\n\t\t\tend - autocompleter.triggerPrefix.length - filterValue.length;\n\t\tconst toInsert = create( { html: renderToString( replacement ) } );\n\n\t\tonChange( insert( record, toInsert, start, end ) );\n\t}\n\n\tfunction select( option: KeyedOption ) {\n\t\tconst { getOptionCompletion } = autocompleter || {};\n\n\t\tif ( option.isDisabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( getOptionCompletion ) {\n\t\t\tconst completion = getOptionCompletion( option.value, filterValue );\n\n\t\t\tconst isCompletionObject = (\n\t\t\t\tobj: OptionCompletion\n\t\t\t): obj is InsertOption | ReplaceOption => {\n\t\t\t\treturn (\n\t\t\t\t\tobj !== null &&\n\t\t\t\t\ttypeof obj === 'object' &&\n\t\t\t\t\t'action' in obj &&\n\t\t\t\t\tobj.action !== undefined &&\n\t\t\t\t\t'value' in obj &&\n\t\t\t\t\tobj.value !== undefined\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tconst completionObject = isCompletionObject( completion )\n\t\t\t\t? completion\n\t\t\t\t: ( {\n\t\t\t\t\t\taction: 'insert-at-caret',\n\t\t\t\t\t\tvalue: completion,\n\t\t\t\t } as InsertOption );\n\n\t\t\tif ( 'replace' === completionObject.action ) {\n\t\t\t\tonReplace( [ completionObject.value ] );\n\t\t\t\t// When replacing, the component will unmount, so don't reset\n\t\t\t\t// state (below) on an unmounted component.\n\t\t\t\treturn;\n\t\t\t} else if ( 'insert-at-caret' === completionObject.action ) {\n\t\t\t\tinsertCompletion( completionObject.value );\n\t\t\t}\n\t\t}\n\n\t\t// Reset autocomplete state after insertion rather than before\n\t\t// so insertion events don't cause the completion menu to redisplay.\n\t\treset();\n\t}\n\n\tfunction reset() {\n\t\tsetSelectedIndex( 0 );\n\t\tsetFilteredOptions( EMPTY_FILTERED_OPTIONS );\n\t\tsetFilterValue( '' );\n\t\tsetAutocompleter( null );\n\t\tsetAutocompleterUI( null );\n\t}\n\n\t/**\n\t * Load options for an autocompleter.\n\t *\n\t * @param {Array} options\n\t */\n\tfunction onChangeOptions( options: Array< KeyedOption > ) {\n\t\tsetSelectedIndex(\n\t\t\toptions.length === filteredOptions.length ? selectedIndex : 0\n\t\t);\n\t\tsetFilteredOptions( options );\n\t}\n\n\tfunction handleKeyDown( event: KeyboardEvent ) {\n\t\tbackspacing.current = event.key === 'Backspace';\n\n\t\tif ( ! autocompleter ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( filteredOptions.length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tevent.defaultPrevented ||\n\t\t\t// Ignore keydowns from IMEs\n\t\t\tevent.isComposing ||\n\t\t\t// Workaround for Mac Safari where the final Enter/Backspace of an IME composition\n\t\t\t// is `isComposing=false`, even though it's technically still part of the composition.\n\t\t\t// These can only be detected by keyCode.\n\t\t\tevent.keyCode === 229\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( event.key ) {\n\t\t\tcase 'ArrowUp': {\n\t\t\t\tconst newIndex =\n\t\t\t\t\t( selectedIndex === 0\n\t\t\t\t\t\t? filteredOptions.length\n\t\t\t\t\t\t: selectedIndex ) - 1;\n\t\t\t\tsetSelectedIndex( newIndex );\n\t\t\t\t// See the related PR as to why this is necessary: https://github.com/WordPress/gutenberg/pull/54902.\n\t\t\t\tif ( isAppleOS() ) {\n\t\t\t\t\tspeak(\n\t\t\t\t\t\tgetNodeText( filteredOptions[ newIndex ].label ),\n\t\t\t\t\t\t'assertive'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 'ArrowDown': {\n\t\t\t\tconst newIndex = ( selectedIndex + 1 ) % filteredOptions.length;\n\t\t\t\tsetSelectedIndex( newIndex );\n\t\t\t\tif ( isAppleOS() ) {\n\t\t\t\t\tspeak(\n\t\t\t\t\t\tgetNodeText( filteredOptions[ newIndex ].label ),\n\t\t\t\t\t\t'assertive'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 'Escape':\n\t\t\t\tsetAutocompleter( null );\n\t\t\t\tsetAutocompleterUI( null );\n\t\t\t\tevent.preventDefault();\n\t\t\t\tbreak;\n\n\t\t\tcase 'Enter':\n\t\t\t\tselect( filteredOptions[ selectedIndex ] );\n\t\t\t\tbreak;\n\n\t\t\tcase 'ArrowLeft':\n\t\t\tcase 'ArrowRight':\n\t\t\t\treset();\n\t\t\t\treturn;\n\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\t// Any handled key should prevent original behavior. This relies on\n\t\t// the early return in the default case.\n\t\tevent.preventDefault();\n\t}\n\n\t// textContent is a primitive (string), memoizing is not strictly necessary\n\t// but this is a preemptive performance improvement, since the autocompleter\n\t// is a potential bottleneck for the editor type metric.\n\tconst textContent = useMemo( () => {\n\t\tif ( isCollapsed( record ) ) {\n\t\t\treturn getTextContent( slice( record, 0 ) );\n\t\t}\n\t\treturn '';\n\t}, [ record ] );\n\n\tuseEffect( () => {\n\t\tif ( ! textContent ) {\n\t\t\tif ( autocompleter ) reset();\n\t\t\treturn;\n\t\t}\n\n\t\t// Find the completer with the highest triggerPrefix index in the\n\t\t// textContent.\n\t\tconst completer = completers.reduce< WPCompleter | null >(\n\t\t\t( lastTrigger, currentCompleter ) => {\n\t\t\t\tconst triggerIndex = textContent.lastIndexOf(\n\t\t\t\t\tcurrentCompleter.triggerPrefix\n\t\t\t\t);\n\t\t\t\tconst lastTriggerIndex =\n\t\t\t\t\tlastTrigger !== null\n\t\t\t\t\t\t? textContent.lastIndexOf( lastTrigger.triggerPrefix )\n\t\t\t\t\t\t: -1;\n\n\t\t\t\treturn triggerIndex > lastTriggerIndex\n\t\t\t\t\t? currentCompleter\n\t\t\t\t\t: lastTrigger;\n\t\t\t},\n\t\t\tnull\n\t\t);\n\n\t\tif ( ! completer ) {\n\t\t\tif ( autocompleter ) reset();\n\t\t\treturn;\n\t\t}\n\n\t\tconst { allowContext, triggerPrefix } = completer;\n\t\tconst triggerIndex = textContent.lastIndexOf( triggerPrefix );\n\t\tconst textWithoutTrigger = textContent.slice(\n\t\t\ttriggerIndex + triggerPrefix.length\n\t\t);\n\n\t\tconst tooDistantFromTrigger = textWithoutTrigger.length > 50; // 50 chars seems to be a good limit.\n\t\t// This is a final barrier to prevent the effect from completing with\n\t\t// an extremely long string, which causes the editor to slow-down\n\t\t// significantly. This could happen, for example, if `matchingWhileBackspacing`\n\t\t// is true and one of the \"words\" end up being too long. If that's the case,\n\t\t// it will be caught by this guard.\n\t\tif ( tooDistantFromTrigger ) return;\n\n\t\tconst mismatch = filteredOptions.length === 0;\n\t\tconst wordsFromTrigger = textWithoutTrigger.split( /\\s/ );\n\t\t// We need to allow the effect to run when not backspacing and if there\n\t\t// was a mismatch. i.e when typing a trigger + the match string or when\n\t\t// clicking in an existing trigger word on the page. We do that if we\n\t\t// detect that we have one word from trigger in the current textual context.\n\t\t//\n\t\t// Ex.: \"Some text @a\" <-- \"@a\" will be detected as the trigger word and\n\t\t// allow the effect to run. It will run until there's a mismatch.\n\t\tconst hasOneTriggerWord = wordsFromTrigger.length === 1;\n\t\t// This is used to allow the effect to run when backspacing and if\n\t\t// \"touching\" a word that \"belongs\" to a trigger. We consider a \"trigger\n\t\t// word\" any word up to the limit of 3 from the trigger character.\n\t\t// Anything beyond that is ignored if there's a mismatch. This allows\n\t\t// us to \"escape\" a mismatch when backspacing, but still imposing some\n\t\t// sane limits.\n\t\t//\n\t\t// Ex: \"Some text @marcelo sekkkk\" <--- \"kkkk\" caused a mismatch, but\n\t\t// if the user presses backspace here, it will show the completion popup again.\n\t\tconst matchingWhileBackspacing =\n\t\t\tbackspacing.current && wordsFromTrigger.length <= 3;\n\n\t\tif ( mismatch && ! ( matchingWhileBackspacing || hasOneTriggerWord ) ) {\n\t\t\tif ( autocompleter ) reset();\n\t\t\treturn;\n\t\t}\n\n\t\tconst textAfterSelection = getTextContent(\n\t\t\tslice( record, undefined, getTextContent( record ).length )\n\t\t);\n\n\t\tif (\n\t\t\tallowContext &&\n\t\t\t! allowContext(\n\t\t\t\ttextContent.slice( 0, triggerIndex ),\n\t\t\t\ttextAfterSelection\n\t\t\t)\n\t\t) {\n\t\t\tif ( autocompleter ) reset();\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\t/^\\s/.test( textWithoutTrigger ) ||\n\t\t\t/\\s\\s+$/.test( textWithoutTrigger )\n\t\t) {\n\t\t\tif ( autocompleter ) reset();\n\t\t\treturn;\n\t\t}\n\n\t\tif ( ! /[\\u0000-\\uFFFF]*$/.test( textWithoutTrigger ) ) {\n\t\t\tif ( autocompleter ) reset();\n\t\t\treturn;\n\t\t}\n\n\t\tconst safeTrigger = escapeRegExp( completer.triggerPrefix );\n\t\tconst text = removeAccents( textContent );\n\t\tconst match = text\n\t\t\t.slice( text.lastIndexOf( completer.triggerPrefix ) )\n\t\t\t.match( new RegExp( `${ safeTrigger }([\\u0000-\\uFFFF]*)$` ) );\n\t\tconst query = match && match[ 1 ];\n\n\t\tsetAutocompleter( completer );\n\t\tsetAutocompleterUI( () =>\n\t\t\tcompleter !== autocompleter\n\t\t\t\t? getAutoCompleterUI( completer )\n\t\t\t\t: AutocompleterUI\n\t\t);\n\t\tsetFilterValue( query === null ? '' : query );\n\t\t// Temporarily disabling exhaustive-deps to avoid introducing unexpected side effecst.\n\t\t// See https://github.com/WordPress/gutenberg/pull/41820\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [ textContent ] );\n\n\tconst { key: selectedKey = '' } = filteredOptions[ selectedIndex ] || {};\n\tconst { className } = autocompleter || {};\n\tconst isExpanded = !! autocompleter && filteredOptions.length > 0;\n\tconst listBoxId = isExpanded\n\t\t? `components-autocomplete-listbox-${ instanceId }`\n\t\t: undefined;\n\tconst activeId = isExpanded\n\t\t? `components-autocomplete-item-${ instanceId }-${ selectedKey }`\n\t\t: null;\n\tconst hasSelection = record.start !== undefined;\n\n\treturn {\n\t\tlistBoxId,\n\t\tactiveId,\n\t\tonKeyDown: handleKeyDown,\n\t\tpopover: hasSelection && AutocompleterUI && (\n\t\t\t<AutocompleterUI\n\t\t\t\tclassName={ className }\n\t\t\t\tfilterValue={ filterValue }\n\t\t\t\tinstanceId={ instanceId }\n\t\t\t\tlistBoxId={ listBoxId }\n\t\t\t\tselectedIndex={ selectedIndex }\n\t\t\t\tonChangeOptions={ onChangeOptions }\n\t\t\t\tonSelect={ select }\n\t\t\t\tvalue={ record }\n\t\t\t\tcontentRef={ contentRef }\n\t\t\t\treset={ reset }\n\t\t\t/>\n\t\t),\n\t};\n}\n\nfunction useLastDifferentValue( value: UseAutocompleteProps[ 'record' ] ) {\n\tconst history = useRef< Set< typeof value > >( new Set() );\n\n\thistory.current.add( value );\n\n\t// Keep the history size to 2.\n\tif ( history.current.size > 2 ) {\n\t\thistory.current.delete( Array.from( history.current )[ 0 ] );\n\t}\n\n\treturn Array.from( history.current )[ 0 ];\n}\n\nexport function useAutocompleteProps( options: UseAutocompleteProps ) {\n\tconst ref = useRef< HTMLElement >( null );\n\tconst onKeyDownRef = useRef< ( event: KeyboardEvent ) => void >();\n\tconst { record } = options;\n\tconst previousRecord = useLastDifferentValue( record );\n\tconst { popover, listBoxId, activeId, onKeyDown } = useAutocomplete( {\n\t\t...options,\n\t\tcontentRef: ref,\n\t} );\n\tonKeyDownRef.current = onKeyDown;\n\n\tconst mergedRefs = useMergeRefs( [\n\t\tref,\n\t\tuseRefEffect( ( element: HTMLElement ) => {\n\t\t\tfunction _onKeyDown( event: KeyboardEvent ) {\n\t\t\t\tonKeyDownRef.current?.( event );\n\t\t\t}\n\t\t\telement.addEventListener( 'keydown', _onKeyDown );\n\t\t\treturn () => {\n\t\t\t\telement.removeEventListener( 'keydown', _onKeyDown );\n\t\t\t};\n\t\t}, [] ),\n\t] );\n\n\t// We only want to show the popover if the user has typed something.\n\tconst didUserInput = record.text !== previousRecord?.text;\n\n\tif ( ! didUserInput ) {\n\t\treturn { ref: mergedRefs };\n\t}\n\n\treturn {\n\t\tref: mergedRefs,\n\t\tchildren: popover,\n\t\t'aria-autocomplete': listBoxId ? 'list' : undefined,\n\t\t'aria-owns': listBoxId,\n\t\t'aria-activedescendant': activeId,\n\t};\n}\n\nexport default function Autocomplete( {\n\tchildren,\n\tisSelected,\n\t...options\n}: AutocompleteProps ) {\n\tconst { popover, ...props } = useAutocomplete( options );\n\treturn (\n\t\t<>\n\t\t\t{ children( props ) }\n\t\t\t{ isSelected && popover }\n\t\t</>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { createElement, Fragment } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
// eslint-disable-next-line no-restricted-imports
|
|
6
|
+
import * as Ariakit from '@ariakit/react';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* WordPress dependencies
|
|
10
|
+
*/
|
|
11
|
+
import { forwardRef, createContext, useContext, useMemo, cloneElement, isValidElement } from '@wordpress/element';
|
|
12
|
+
import { isRTL } from '@wordpress/i18n';
|
|
13
|
+
import { check, chevronRightSmall } from '@wordpress/icons';
|
|
14
|
+
import { SVG, Circle } from '@wordpress/primitives';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Internal dependencies
|
|
18
|
+
*/
|
|
19
|
+
import { useContextSystem, contextConnect } from '../context';
|
|
20
|
+
import Icon from '../icon';
|
|
21
|
+
import * as Styled from './styles';
|
|
22
|
+
export const DropdownMenuContext = createContext(undefined);
|
|
23
|
+
export const DropdownMenuItem = forwardRef(function DropdownMenuItem({
|
|
24
|
+
prefix,
|
|
25
|
+
suffix,
|
|
26
|
+
children,
|
|
27
|
+
hideOnClick = true,
|
|
28
|
+
...props
|
|
29
|
+
}, ref) {
|
|
30
|
+
const dropdownMenuContext = useContext(DropdownMenuContext);
|
|
31
|
+
return createElement(Styled.DropdownMenuItem, {
|
|
32
|
+
ref: ref,
|
|
33
|
+
...props,
|
|
34
|
+
hideOnClick: hideOnClick,
|
|
35
|
+
store: dropdownMenuContext?.store
|
|
36
|
+
}, prefix && createElement(Styled.ItemPrefixWrapper, null, prefix), children, suffix && createElement(Styled.ItemSuffixWrapper, null, suffix));
|
|
37
|
+
});
|
|
38
|
+
export const DropdownMenuCheckboxItem = forwardRef(function DropdownMenuCheckboxItem({
|
|
39
|
+
suffix,
|
|
40
|
+
children,
|
|
41
|
+
hideOnClick = false,
|
|
42
|
+
...props
|
|
43
|
+
}, ref) {
|
|
44
|
+
const dropdownMenuContext = useContext(DropdownMenuContext);
|
|
45
|
+
return createElement(Styled.DropdownMenuCheckboxItem, {
|
|
46
|
+
ref: ref,
|
|
47
|
+
...props,
|
|
48
|
+
hideOnClick: hideOnClick,
|
|
49
|
+
store: dropdownMenuContext?.store
|
|
50
|
+
}, createElement(Ariakit.MenuItemCheck, {
|
|
51
|
+
store: dropdownMenuContext?.store,
|
|
52
|
+
render: createElement(Styled.ItemPrefixWrapper, null)
|
|
53
|
+
}, createElement(Icon, {
|
|
54
|
+
icon: check,
|
|
55
|
+
size: 24
|
|
56
|
+
})), children, suffix && createElement(Styled.ItemSuffixWrapper, null, suffix));
|
|
57
|
+
});
|
|
58
|
+
export const DropdownMenuRadioItem = forwardRef(function DropdownMenuRadioItem({
|
|
59
|
+
suffix,
|
|
60
|
+
children,
|
|
61
|
+
hideOnClick = false,
|
|
62
|
+
...props
|
|
63
|
+
}, ref) {
|
|
64
|
+
const dropdownMenuContext = useContext(DropdownMenuContext);
|
|
65
|
+
return createElement(Styled.DropdownMenuRadioItem, {
|
|
66
|
+
ref: ref,
|
|
67
|
+
...props,
|
|
68
|
+
hideOnClick: hideOnClick,
|
|
69
|
+
store: dropdownMenuContext?.store
|
|
70
|
+
}, createElement(Ariakit.MenuItemCheck, {
|
|
71
|
+
store: dropdownMenuContext?.store,
|
|
72
|
+
render: createElement(Styled.ItemPrefixWrapper, null)
|
|
73
|
+
}, createElement(SVG, {
|
|
74
|
+
viewBox: "0 0 24 24",
|
|
75
|
+
xmlns: "http://www.w3.org/2000/svg"
|
|
76
|
+
}, createElement(Circle, {
|
|
77
|
+
cx: 12,
|
|
78
|
+
cy: 12,
|
|
79
|
+
r: 3,
|
|
80
|
+
fill: "currentColor"
|
|
81
|
+
}))), children, suffix);
|
|
82
|
+
});
|
|
83
|
+
export const DropdownMenuGroup = forwardRef(function DropdownMenuGroup(props, ref) {
|
|
84
|
+
const dropdownMenuContext = useContext(DropdownMenuContext);
|
|
85
|
+
return createElement(Styled.DropdownMenuGroup, {
|
|
86
|
+
ref: ref,
|
|
87
|
+
...props,
|
|
88
|
+
store: dropdownMenuContext?.store
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
export const DropdownMenuGroupLabel = forwardRef(function DropdownMenuGroupLabel(props, ref) {
|
|
92
|
+
const dropdownMenuContext = useContext(DropdownMenuContext);
|
|
93
|
+
return createElement(Styled.DropdownMenuGroupLabel, {
|
|
94
|
+
ref: ref,
|
|
95
|
+
...props,
|
|
96
|
+
store: dropdownMenuContext?.store
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
const UnconnectedDropdownMenu = (props, ref) => {
|
|
100
|
+
var _props$placement, _trigger$props$suffix;
|
|
101
|
+
const {
|
|
102
|
+
// Store props
|
|
103
|
+
open,
|
|
104
|
+
defaultOpen = false,
|
|
105
|
+
onOpenChange,
|
|
106
|
+
placement,
|
|
107
|
+
// Menu trigger props
|
|
108
|
+
trigger,
|
|
109
|
+
// Menu props
|
|
110
|
+
gutter,
|
|
111
|
+
children,
|
|
112
|
+
shift,
|
|
113
|
+
modal = true,
|
|
114
|
+
hideOnEscape = true,
|
|
115
|
+
// From internal components context
|
|
116
|
+
variant,
|
|
117
|
+
// Rest
|
|
118
|
+
...otherProps
|
|
119
|
+
} = useContextSystem(props, 'DropdownMenu');
|
|
120
|
+
const parentContext = useContext(DropdownMenuContext);
|
|
121
|
+
const computedDirection = isRTL() ? 'rtl' : 'ltr';
|
|
122
|
+
|
|
123
|
+
// If an explicit value for the `placement` prop is not passed,
|
|
124
|
+
// apply a default placement of `bottom-start` for the root dropdown,
|
|
125
|
+
// and of `right-start` for nested dropdowns.
|
|
126
|
+
let computedPlacement = (_props$placement = props.placement) !== null && _props$placement !== void 0 ? _props$placement : parentContext?.store ? 'right-start' : 'bottom-start';
|
|
127
|
+
// Swap left/right in case of RTL direction
|
|
128
|
+
if (computedDirection === 'rtl') {
|
|
129
|
+
if (/right/.test(computedPlacement)) {
|
|
130
|
+
computedPlacement = computedPlacement.replace('right', 'left');
|
|
131
|
+
} else if (/left/.test(computedPlacement)) {
|
|
132
|
+
computedPlacement = computedPlacement.replace('left', 'right');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const dropdownMenuStore = Ariakit.useMenuStore({
|
|
136
|
+
parent: parentContext?.store,
|
|
137
|
+
open,
|
|
138
|
+
defaultOpen,
|
|
139
|
+
placement: computedPlacement,
|
|
140
|
+
focusLoop: true,
|
|
141
|
+
setOpen(willBeOpen) {
|
|
142
|
+
onOpenChange?.(willBeOpen);
|
|
143
|
+
},
|
|
144
|
+
rtl: computedDirection === 'rtl'
|
|
145
|
+
});
|
|
146
|
+
const contextValue = useMemo(() => ({
|
|
147
|
+
store: dropdownMenuStore,
|
|
148
|
+
variant
|
|
149
|
+
}), [dropdownMenuStore, variant]);
|
|
150
|
+
|
|
151
|
+
// Extract the side from the applied placement — useful for animations.
|
|
152
|
+
const appliedPlacementSide = dropdownMenuStore.useState('placement').split('-')[0];
|
|
153
|
+
if (dropdownMenuStore.parent && !(isValidElement(trigger) && DropdownMenuItem === trigger.type)) {
|
|
154
|
+
// eslint-disable-next-line no-console
|
|
155
|
+
console.warn('For nested DropdownMenus, the `trigger` should always be a `DropdownMenuItem`.');
|
|
156
|
+
}
|
|
157
|
+
return createElement(Fragment, null, createElement(Ariakit.MenuButton, {
|
|
158
|
+
ref: ref,
|
|
159
|
+
store: dropdownMenuStore,
|
|
160
|
+
render: dropdownMenuStore.parent ? cloneElement(trigger, {
|
|
161
|
+
// Add submenu arrow, unless a `suffix` is explicitly specified
|
|
162
|
+
suffix: (_trigger$props$suffix = trigger.props.suffix) !== null && _trigger$props$suffix !== void 0 ? _trigger$props$suffix : createElement(Styled.SubmenuChevronIcon, {
|
|
163
|
+
"aria-hidden": "true",
|
|
164
|
+
icon: chevronRightSmall,
|
|
165
|
+
size: 24
|
|
166
|
+
})
|
|
167
|
+
}) : trigger
|
|
168
|
+
}), createElement(Styled.DropdownMenu, {
|
|
169
|
+
...otherProps,
|
|
170
|
+
modal: modal,
|
|
171
|
+
store: dropdownMenuStore,
|
|
172
|
+
gutter: gutter !== null && gutter !== void 0 ? gutter : dropdownMenuStore.parent ? 16 : 8,
|
|
173
|
+
shift: shift !== null && shift !== void 0 ? shift : dropdownMenuStore.parent ? -8 : 0,
|
|
174
|
+
hideOnHoverOutside: false,
|
|
175
|
+
"data-side": appliedPlacementSide,
|
|
176
|
+
variant: variant,
|
|
177
|
+
wrapperProps: {
|
|
178
|
+
dir: computedDirection,
|
|
179
|
+
style: {
|
|
180
|
+
direction: computedDirection
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
hideOnEscape: hideOnEscape,
|
|
184
|
+
unmountOnHide: true
|
|
185
|
+
}, createElement(DropdownMenuContext.Provider, {
|
|
186
|
+
value: contextValue
|
|
187
|
+
}, children)));
|
|
188
|
+
};
|
|
189
|
+
export const DropdownMenu = contextConnect(UnconnectedDropdownMenu, 'DropdownMenu');
|
|
190
|
+
export const DropdownMenuSeparator = forwardRef(function DropdownMenuSeparator(props, ref) {
|
|
191
|
+
const dropdownMenuContext = useContext(DropdownMenuContext);
|
|
192
|
+
return createElement(Styled.DropdownMenuSeparator, {
|
|
193
|
+
ref: ref,
|
|
194
|
+
...props,
|
|
195
|
+
store: dropdownMenuContext?.store,
|
|
196
|
+
variant: dropdownMenuContext?.variant
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
//# sourceMappingURL=index.js.map
|