@haiilo/catalyst 14.1.0 → 14.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4893,6 +4893,71 @@ function computeCoordsFromPlacement(_ref, placement, rtl) {
4893
4893
  return coords;
4894
4894
  }
4895
4895
 
4896
+ /**
4897
+ * Resolves with an object of overflow side offsets that determine how much the
4898
+ * element is overflowing a given clipping boundary on each side.
4899
+ * - positive = overflowing the boundary by that number of pixels
4900
+ * - negative = how many pixels left before it will overflow
4901
+ * - 0 = lies flush with the boundary
4902
+ * @see https://floating-ui.com/docs/detectOverflow
4903
+ */
4904
+ async function detectOverflow(state, options) {
4905
+ var _await$platform$isEle;
4906
+ if (options === void 0) {
4907
+ options = {};
4908
+ }
4909
+ const {
4910
+ x,
4911
+ y,
4912
+ platform,
4913
+ rects,
4914
+ elements,
4915
+ strategy
4916
+ } = state;
4917
+ const {
4918
+ boundary = 'clippingAncestors',
4919
+ rootBoundary = 'viewport',
4920
+ elementContext = 'floating',
4921
+ altBoundary = false,
4922
+ padding = 0
4923
+ } = evaluate(options, state);
4924
+ const paddingObject = getPaddingObject(padding);
4925
+ const altContext = elementContext === 'floating' ? 'reference' : 'floating';
4926
+ const element = elements[altBoundary ? altContext : elementContext];
4927
+ const clippingClientRect = rectToClientRect(await platform.getClippingRect({
4928
+ element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),
4929
+ boundary,
4930
+ rootBoundary,
4931
+ strategy
4932
+ }));
4933
+ const rect = elementContext === 'floating' ? {
4934
+ x,
4935
+ y,
4936
+ width: rects.floating.width,
4937
+ height: rects.floating.height
4938
+ } : rects.reference;
4939
+ const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
4940
+ const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
4941
+ x: 1,
4942
+ y: 1
4943
+ } : {
4944
+ x: 1,
4945
+ y: 1
4946
+ };
4947
+ const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({
4948
+ elements,
4949
+ rect,
4950
+ offsetParent,
4951
+ strategy
4952
+ }) : rect);
4953
+ return {
4954
+ top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,
4955
+ bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,
4956
+ left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,
4957
+ right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x
4958
+ };
4959
+ }
4960
+
4896
4961
  /**
4897
4962
  * Computes the `x` and `y` coordinates that will place the floating element
4898
4963
  * next to a given reference element.
@@ -4922,6 +4987,7 @@ const computePosition$1 = async (reference, floating, config) => {
4922
4987
  let middlewareData = {};
4923
4988
  let resetCount = 0;
4924
4989
  for (let i = 0; i < validMiddleware.length; i++) {
4990
+ var _platform$detectOverf;
4925
4991
  const {
4926
4992
  name,
4927
4993
  fn
@@ -4939,7 +5005,10 @@ const computePosition$1 = async (reference, floating, config) => {
4939
5005
  strategy,
4940
5006
  middlewareData,
4941
5007
  rects,
4942
- platform,
5008
+ platform: {
5009
+ ...platform,
5010
+ detectOverflow: (_platform$detectOverf = platform.detectOverflow) != null ? _platform$detectOverf : detectOverflow
5011
+ },
4943
5012
  elements: {
4944
5013
  reference,
4945
5014
  floating
@@ -4984,71 +5053,6 @@ const computePosition$1 = async (reference, floating, config) => {
4984
5053
  };
4985
5054
  };
4986
5055
 
4987
- /**
4988
- * Resolves with an object of overflow side offsets that determine how much the
4989
- * element is overflowing a given clipping boundary on each side.
4990
- * - positive = overflowing the boundary by that number of pixels
4991
- * - negative = how many pixels left before it will overflow
4992
- * - 0 = lies flush with the boundary
4993
- * @see https://floating-ui.com/docs/detectOverflow
4994
- */
4995
- async function detectOverflow(state, options) {
4996
- var _await$platform$isEle;
4997
- if (options === void 0) {
4998
- options = {};
4999
- }
5000
- const {
5001
- x,
5002
- y,
5003
- platform,
5004
- rects,
5005
- elements,
5006
- strategy
5007
- } = state;
5008
- const {
5009
- boundary = 'clippingAncestors',
5010
- rootBoundary = 'viewport',
5011
- elementContext = 'floating',
5012
- altBoundary = false,
5013
- padding = 0
5014
- } = evaluate(options, state);
5015
- const paddingObject = getPaddingObject(padding);
5016
- const altContext = elementContext === 'floating' ? 'reference' : 'floating';
5017
- const element = elements[altBoundary ? altContext : elementContext];
5018
- const clippingClientRect = rectToClientRect(await platform.getClippingRect({
5019
- element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),
5020
- boundary,
5021
- rootBoundary,
5022
- strategy
5023
- }));
5024
- const rect = elementContext === 'floating' ? {
5025
- x,
5026
- y,
5027
- width: rects.floating.width,
5028
- height: rects.floating.height
5029
- } : rects.reference;
5030
- const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
5031
- const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
5032
- x: 1,
5033
- y: 1
5034
- } : {
5035
- x: 1,
5036
- y: 1
5037
- };
5038
- const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({
5039
- elements,
5040
- rect,
5041
- offsetParent,
5042
- strategy
5043
- }) : rect);
5044
- return {
5045
- top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,
5046
- bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,
5047
- left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,
5048
- right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x
5049
- };
5050
- }
5051
-
5052
5056
  /**
5053
5057
  * Optimizes the visibility of the floating element by flipping the `placement`
5054
5058
  * in order to keep it in view when the preferred placement(s) will overflow the
@@ -5099,7 +5103,7 @@ const flip$1 = function (options) {
5099
5103
  fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));
5100
5104
  }
5101
5105
  const placements = [initialPlacement, ...fallbackPlacements];
5102
- const overflow = await detectOverflow(state, detectOverflowOptions);
5106
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
5103
5107
  const overflows = [];
5104
5108
  let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];
5105
5109
  if (checkMainAxis) {
@@ -5283,7 +5287,8 @@ const shift$1 = function (options) {
5283
5287
  const {
5284
5288
  x,
5285
5289
  y,
5286
- placement
5290
+ placement,
5291
+ platform
5287
5292
  } = state;
5288
5293
  const {
5289
5294
  mainAxis: checkMainAxis = true,
@@ -5306,7 +5311,7 @@ const shift$1 = function (options) {
5306
5311
  x,
5307
5312
  y
5308
5313
  };
5309
- const overflow = await detectOverflow(state, detectOverflowOptions);
5314
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
5310
5315
  const crossAxis = getSideAxis(getSide(placement));
5311
5316
  const mainAxis = getOppositeAxis(crossAxis);
5312
5317
  let mainAxisCoord = coords[mainAxis];
@@ -5370,7 +5375,7 @@ const size$1 = function (options) {
5370
5375
  apply = () => {},
5371
5376
  ...detectOverflowOptions
5372
5377
  } = evaluate(options, state);
5373
- const overflow = await detectOverflow(state, detectOverflowOptions);
5378
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
5374
5379
  const side = getSide(placement);
5375
5380
  const alignment = getAlignment(placement);
5376
5381
  const isYAxis = getSideAxis(placement) === 'y';
@@ -7874,10 +7879,25 @@ const CatDropdown = class {
7874
7879
  }
7875
7880
  })
7876
7881
  ];
7882
+ const middleware = [offset(CatDropdown.OFFSET)];
7883
+ const flipMiddleware = flip({
7884
+ // Ensure we flip to the perpendicular axis if it doesn't fit
7885
+ // on narrow viewports.
7886
+ crossAxis: 'alignment',
7887
+ fallbackAxisSideDirection: 'end'
7888
+ });
7889
+ const shiftMiddleware = shift();
7890
+ // Prioritize flip over shift for edge-aligned placements only.
7891
+ if (this.placement.includes('-')) {
7892
+ middleware.push(flipMiddleware, shiftMiddleware);
7893
+ }
7894
+ else {
7895
+ middleware.push(shiftMiddleware, flipMiddleware);
7896
+ }
7877
7897
  computePosition(anchorElement, this.content, {
7878
7898
  strategy: 'fixed',
7879
7899
  placement: this.placement,
7880
- middleware: [offset(CatDropdown.OFFSET), flip(), shift(), ...resize]
7900
+ middleware: [offset(CatDropdown.OFFSET), ...middleware, ...resize]
7881
7901
  }).then(({ x, y, placement }) => {
7882
7902
  this.content.dataset.placement = placement;
7883
7903
  Object.assign(this.content.style, {
@@ -9373,21 +9393,27 @@ const CatSelect = class {
9373
9393
  options
9374
9394
  });
9375
9395
  });
9396
+ this.renderSubscription?.unsubscribe();
9397
+ if (connector.renderOptions$) {
9398
+ this.renderSubscription = connector.renderOptions$.subscribe(() => {
9399
+ this.rerenderOptions();
9400
+ });
9401
+ }
9376
9402
  }
9377
9403
  render() {
9378
9404
  this.hostElement.tabIndex = Number(this.hostElement.getAttribute('tabindex')) || 0;
9379
- return (index.h(index.Host, { key: '044a13b28c3c3d3fcb5b06efa53d489783ae9698' }, index.h("div", { key: 'b540d0b58849b8b401c611dfa08da42f45a7953c', class: {
9405
+ return (index.h(index.Host, { key: '7489b4123c900ebefa06dcebde32b0a4ee52d4a3' }, index.h("div", { key: '9669441806e8bebc5f583957cc1a24330f06085a', class: {
9380
9406
  'select-field': true,
9381
9407
  'select-horizontal': this.horizontal ?? this.fallbackHorizontal ?? false,
9382
9408
  'select-multiple': this.multiple
9383
- } }, index.h("div", { key: '3864749c06c0aa54df1912f90636094dcdd4a229', class: { 'label-container': true, hidden: this.labelHidden } }, (this.hasSlottedLabel || this.label) && (index.h("label", { key: 'b2e64f375a8d2e9430007b548f468055a1a83b9b', htmlFor: `select-${this.id}-input`, part: "label" }, index.h("span", { key: '1d09f458ed23045ecbd3ca3b9bb2fa5740f6c4e1', class: "label-wrapper" }, (this.hasSlottedLabel && index.h("slot", { key: '7c569d0f97e2c48d6515e051dd8098003b0dc2c2', name: "label" })) || this.label, index.h("div", { key: 'f3c8709ea17c26d65e41ceb505af51dac81dda37', class: "label-metadata" }, !this.required && (this.requiredMarker ?? 'optional').startsWith('optional') && (index.h("span", { key: 'f2cc0d4a5fd0d815a1087b7f2b1c55c73ca36e93', class: "label-optional", "aria-hidden": "true" }, "(", index$1.catI18nRegistry.t('input.optional'), ")")), this.required && this.requiredMarker?.startsWith('required') && (index.h("span", { key: 'beb3aaaf8261978be7895a1580a42f25f65ef5e7', class: "label-optional", "aria-hidden": "true" }, "(", index$1.catI18nRegistry.t('input.required'), ")"))))))), index.h("div", { key: '23a30b437dca6aea6d6f01156dc6c56faae3912f', class: "select-container" }, index.h("div", { key: '146509fd8146b3afa9c5157c7a37198c810330d7', class: { 'select-wrapper': true, 'select-disabled': this.disabled, 'select-invalid': this.invalid }, ref: el => (this.trigger = el), id: this.id, role: "combobox", "aria-expanded": this.state.isOpen || this.isPillboxActive(), "aria-controls": this.isPillboxActive() ? `select-pillbox-${this.id}` : `select-listbox-${this.id}`, "aria-required": this.required ? 'true' : false, "aria-activedescendant": this.activeDescendant, onClick: e => this.onClick(e) }, index.h("div", { key: 'f9f8b2cc0914ba4a7151c580f9e9eda332aad35e', class: "select-wrapper-inner" }, this.multiple && this.state.selection.length ? (index.h("div", { id: `select-pillbox-${this.id}`, role: "listbox", "aria-orientation": "horizontal", class: "select-pills" }, this.state.selection.map((item, i) => (index.h("span", { class: {
9409
+ } }, index.h("div", { key: 'a94a2217157c125e34802b140843d2fffd63283f', class: { 'label-container': true, hidden: this.labelHidden } }, (this.hasSlottedLabel || this.label) && (index.h("label", { key: '557e2754156cb4484972dcccca103451db00a01e', htmlFor: `select-${this.id}-input`, part: "label" }, index.h("span", { key: '8d229578a218717dbe78a63e416cba36cc300c37', class: "label-wrapper" }, (this.hasSlottedLabel && index.h("slot", { key: 'f1700687e21b73edce905bc8325479bed8c31962', name: "label" })) || this.label, index.h("div", { key: '109009794bab604eca5d3f690858145ac770ea81', class: "label-metadata" }, !this.required && (this.requiredMarker ?? 'optional').startsWith('optional') && (index.h("span", { key: '5868ecd309ab485a60439fd6743be56947f9d43e', class: "label-optional", "aria-hidden": "true" }, "(", index$1.catI18nRegistry.t('input.optional'), ")")), this.required && this.requiredMarker?.startsWith('required') && (index.h("span", { key: '8e61a17e1d1b9f3fc584c08824b243b5f0c07c0f', class: "label-optional", "aria-hidden": "true" }, "(", index$1.catI18nRegistry.t('input.required'), ")"))))))), index.h("div", { key: '9d211cd7674cda6f9bcfeebaf1252055239421ce', class: "select-container" }, index.h("div", { key: '878137436714dff589d4731ada14d11e443ab4a6', class: { 'select-wrapper': true, 'select-disabled': this.disabled, 'select-invalid': this.invalid }, ref: el => (this.trigger = el), id: this.id, role: "combobox", "aria-expanded": this.state.isOpen || this.isPillboxActive(), "aria-controls": this.isPillboxActive() ? `select-pillbox-${this.id}` : `select-listbox-${this.id}`, "aria-required": this.required ? 'true' : false, "aria-activedescendant": this.activeDescendant, onClick: e => this.onClick(e) }, index.h("div", { key: '7a268001a9bc895aa5fd1157a57f89555ad9e868', class: "select-wrapper-inner" }, this.multiple && this.state.selection.length ? (index.h("div", { id: `select-pillbox-${this.id}`, role: "listbox", "aria-orientation": "horizontal", class: "select-pills" }, this.state.selection.map((item, i) => (index.h("span", { class: {
9384
9410
  pill: true,
9385
9411
  'select-no-open': true,
9386
9412
  'select-option-active': this.state.activeSelectionIndex === i
9387
- }, role: "option", "aria-selected": "true", id: `select-${this.id}-selection-${i}` }, item.render.avatar ? (index.h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, icon: item.render.avatar.icon, initials: item.render.avatar.initials ?? '' })) : null, index.h("span", null, item.render.label), !this.disabled && (index.h("cat-button", { size: "xs", variant: "text", icon: "$cat:select-clear", iconOnly: true, a11yLabel: index$1.catI18nRegistry.t('select.deselect'), onClick: () => this.deselect(item.item.id), tabIndex: -1, "data-dropdown-no-close": true }))))))) : this.state.selection.length && this.state.selection[0].render.avatar ? (index.h("cat-avatar", { label: this.state.selection[0].render.label, round: this.state.selection[0].render.avatar.round, src: this.state.selection[0].render.avatar.src, icon: this.state.selection[0].render.avatar.icon, initials: this.state.selection[0].render.avatar.initials ?? '' })) : null, index.h("input", { key: 'ccf158ead3c32c1376744366ccae13d32762e150', "data-test": this.testId, ...this.nativeAttributes, part: "input", id: `select-${this.id}-input`, class: "select-input", role: "combobox", ref: el => (this.input = el), "aria-controls": this.isPillboxActive() ? `select-pillbox-${this.id}` : `select-listbox-${this.id}`, "aria-activedescendant": this.activeDescendant, "aria-invalid": this.invalid ? 'true' : undefined, "aria-describedby": this.hasHint ? this.id + '-hint' : undefined, "aria-autocomplete": "list", onInput: this.onInput.bind(this), value: !this.multiple ? this.state.term : undefined, placeholder: this.placeholder, disabled: this.disabled || this.state.isResolving })), this.state.isResolving && index.h("cat-spinner", { key: '8af750f50e620a73f9a35c66708293e758a2786e' }), this.invalid && (index.h("cat-icon", { key: '114ead7c9b473945a1fb2f5774e74d75c57819f5', icon: "$cat:input-error", class: "icon-suffix cat-text-danger", size: "l" })), (this.state.selection.length || this.state.term.length) &&
9413
+ }, role: "option", "aria-selected": "true", id: `select-${this.id}-selection-${i}` }, item.render.avatar ? (index.h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, icon: item.render.avatar.icon, initials: item.render.avatar.initials ?? '' })) : null, index.h("span", null, item.render.label), !this.disabled && (index.h("cat-button", { size: "xs", variant: "text", icon: "$cat:select-clear", iconOnly: true, a11yLabel: index$1.catI18nRegistry.t('select.deselect'), onClick: () => this.deselect(item.item.id), tabIndex: -1, "data-dropdown-no-close": true }))))))) : this.state.selection.length && this.state.selection[0].render.avatar ? (index.h("cat-avatar", { label: this.state.selection[0].render.label, round: this.state.selection[0].render.avatar.round, src: this.state.selection[0].render.avatar.src, icon: this.state.selection[0].render.avatar.icon, initials: this.state.selection[0].render.avatar.initials ?? '' })) : null, index.h("input", { key: 'dd9c6f767f5cfc9c2e3e0f37dd4bad075f1169c8', "data-test": this.testId, ...this.nativeAttributes, part: "input", id: `select-${this.id}-input`, class: "select-input", role: "combobox", ref: el => (this.input = el), "aria-controls": this.isPillboxActive() ? `select-pillbox-${this.id}` : `select-listbox-${this.id}`, "aria-activedescendant": this.activeDescendant, "aria-invalid": this.invalid ? 'true' : undefined, "aria-describedby": this.hasHint ? this.id + '-hint' : undefined, "aria-autocomplete": "list", onInput: this.onInput.bind(this), value: !this.multiple ? this.state.term : undefined, placeholder: this.placeholder, disabled: this.disabled || this.state.isResolving })), this.state.isResolving && index.h("cat-spinner", { key: 'c3ed10971f8f29d352df71a5bb577ff3f4499ccd' }), this.invalid && (index.h("cat-icon", { key: 'c4788a44a097252f58c43769edec339c57ed74e4', icon: "$cat:input-error", class: "icon-suffix cat-text-danger", size: "l" })), (this.state.selection.length || this.state.term.length) &&
9388
9414
  !this.disabled &&
9389
9415
  !this.state.isResolving &&
9390
- this.clearable ? (index.h("cat-button", { id: `select-clear-btn-${this.id}`, iconOnly: true, icon: "$cat:input-close", variant: "text", size: "s", a11yLabel: index$1.catI18nRegistry.t('input.clear'), onCatClick: () => this.clearInput(), "data-dropdown-no-close": true })) : null, !this.state.isResolving && (index.h("cat-button", { key: 'ece4331f89cbb9c37d9f9693800bca1320ff7f37', iconOnly: true, icon: "$cat:select-open", class: { 'select-btn': true, 'select-btn-open': this.state.isOpen }, variant: "text", size: "s", a11yLabel: this.state.isOpen ? index$1.catI18nRegistry.t('select.close') : index$1.catI18nRegistry.t('select.open'), "aria-controls": `select-listbox-${this.id}`, "aria-expanded": this.state.isOpen, tabIndex: -1, disabled: this.disabled || this.state.isResolving, "data-dropdown-no-close": true }))), this.hasHint && (index.h(CatFormHint, { key: 'd25455be1db5404a698b35d088ba0a303215a321', id: this.id, hint: this.hint, slottedHint: this.hasSlottedHint && index.h("slot", { name: "hint" }), errorMap: this.errorMap })))), index.h("div", { key: 'c58c1914f90b0fb9a7b40c4c37e2fe7d92877ab8', class: "select-dropdown", ref: el => (this.dropdown = el), style: { display: this.state.isOpen ? 'block' : undefined } }, this.state.isOpen && (index.h("cat-scrollable", { key: '73a6a048ba31d8f5944d4a1aa6c8c4fb96e56df2', class: "select-options-wrapper", scrolledBuffer: 56, noOverflowX: true, noOverscroll: true, noScrolledInit: true, onScrolledBottom: () => this.more$.next() }, index.h("ul", { key: '4b86961480022fd7dd0e1641fdaed8116e320090', class: "select-options", role: "listbox", "aria-multiselectable": this.multiple, "aria-setsize": this.state.totalElements, id: `select-listbox-${this.id}` }, this.optionsList, this.state.isFirstLoading
9416
+ this.clearable ? (index.h("cat-button", { id: `select-clear-btn-${this.id}`, iconOnly: true, icon: "$cat:input-close", variant: "text", size: "s", a11yLabel: index$1.catI18nRegistry.t('input.clear'), onCatClick: () => this.clearInput(), "data-dropdown-no-close": true })) : null, !this.state.isResolving && (index.h("cat-button", { key: 'a1ae4dfc03feec1a556f818ea08ba8a53b10f132', iconOnly: true, icon: "$cat:select-open", class: { 'select-btn': true, 'select-btn-open': this.state.isOpen }, variant: "text", size: "s", a11yLabel: this.state.isOpen ? index$1.catI18nRegistry.t('select.close') : index$1.catI18nRegistry.t('select.open'), "aria-controls": `select-listbox-${this.id}`, "aria-expanded": this.state.isOpen, tabIndex: -1, disabled: this.disabled || this.state.isResolving, "data-dropdown-no-close": true }))), this.hasHint && (index.h(CatFormHint, { key: '2557e44ce584d96cc8497cee27d8e6e8f6464fd9', id: this.id, hint: this.hint, slottedHint: this.hasSlottedHint && index.h("slot", { name: "hint" }), errorMap: this.errorMap })))), index.h("div", { key: '795de862359d06464591e32d3a410a8974a55028', class: "select-dropdown", ref: el => (this.dropdown = el), style: { display: this.state.isOpen ? 'block' : undefined } }, this.state.isOpen && (index.h("cat-scrollable", { key: 'b88fc1b204533e3714b8533c10b7a817fe2d4ef1', class: "select-options-wrapper", scrolledBuffer: 56, noOverflowX: true, noOverscroll: true, noScrolledInit: true, onScrolledBottom: () => this.more$.next() }, index.h("ul", { key: 'f0fe6e0c398c7682363174ec6e9f04eaa8e25073', class: "select-options", role: "listbox", "aria-multiselectable": this.multiple, "aria-setsize": this.state.totalElements, id: `select-listbox-${this.id}` }, this.optionsList, this.state.isFirstLoading
9391
9417
  ? Array.from(Array(CatSelect.SKELETON_COUNT)).map(() => (index.h("li", { class: "select-option-loading" }, index.h("cat-skeleton", { variant: "body", lines: 1 }), index.h("cat-skeleton", { variant: "body", lines: 1 }))))
9392
9418
  : !this.state.options.length &&
9393
9419
  !this.tags && (index.h("li", { class: "select-option-empty" }, this.noItems ? this.noItems : index$1.catI18nRegistry.t('select.empty')))))))));
@@ -9411,7 +9437,7 @@ const CatSelect = class {
9411
9437
  return (index.h("li", { role: "option", class: "select-option", id: `select-${this.id}-option-${i}`, "aria-selected": isOptionSelected ? 'true' : 'false' }, this.multiple ? (index.h("cat-checkbox", { class: { 'select-option-active': this.state.activeOptionIndex === i }, checked: isOptionSelected, tabIndex: -1, labelLeft: true, onFocus: () => this.input?.focus(), onCatChange: e => {
9412
9438
  !isTagOption ? this.toggle(item) : this.toggleTag(item);
9413
9439
  e.stopPropagation();
9414
- } }, index.h("span", { slot: "label", class: "select-option-inner" }, item.render.avatar ? (index.h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, icon: item.render.avatar.icon, initials: item.render.avatar.initials ?? '' })) : null, index.h("span", { class: "select-option-text" }, index.h("span", { class: "select-option-label" }, getLabel()), index.h("span", { class: "select-option-description" }, item.render.description))))) : (index.h("div", { class: {
9440
+ } }, index.h("span", { slot: "label", class: "select-option-inner" }, item.render.avatar ? (index.h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, icon: item.render.avatar.icon, initials: item.render.avatar.initials ?? '' })) : null, index.h("span", { class: "select-option-text", part: "option" }, index.h("span", { class: "select-option-label" }, getLabel()), index.h("span", { class: "select-option-description" }, item.render.description))))) : (index.h("div", { class: {
9415
9441
  'select-option-inner': true,
9416
9442
  'select-option-single': true,
9417
9443
  'select-option-active': this.state.activeOptionIndex === i
@@ -9509,6 +9535,11 @@ const CatSelect = class {
9509
9535
  });
9510
9536
  }
9511
9537
  }
9538
+ rerenderOptions() {
9539
+ const optionItems = this.state.options.map(o => o.item);
9540
+ const updatedOptions = this.toSelectItems(this.connector, optionItems);
9541
+ this.patchState({ options: updatedOptions });
9542
+ }
9512
9543
  toggle(item) {
9513
9544
  this.isSelected(item.item.id)
9514
9545
  ? this.deselect(item.item.id)
@@ -9530,6 +9561,8 @@ const CatSelect = class {
9530
9561
  this.connector = connector ?? this.connector;
9531
9562
  this.subscription?.unsubscribe();
9532
9563
  this.subscription = undefined;
9564
+ this.renderSubscription?.unsubscribe();
9565
+ this.renderSubscription = undefined;
9533
9566
  this.state = INIT_STATE;
9534
9567
  }
9535
9568
  onClick(event) {
@@ -264,10 +264,25 @@ export class CatDropdown {
264
264
  }
265
265
  })
266
266
  ];
267
+ const middleware = [offset(CatDropdown.OFFSET)];
268
+ const flipMiddleware = flip({
269
+ // Ensure we flip to the perpendicular axis if it doesn't fit
270
+ // on narrow viewports.
271
+ crossAxis: 'alignment',
272
+ fallbackAxisSideDirection: 'end'
273
+ });
274
+ const shiftMiddleware = shift();
275
+ // Prioritize flip over shift for edge-aligned placements only.
276
+ if (this.placement.includes('-')) {
277
+ middleware.push(flipMiddleware, shiftMiddleware);
278
+ }
279
+ else {
280
+ middleware.push(shiftMiddleware, flipMiddleware);
281
+ }
267
282
  computePosition(anchorElement, this.content, {
268
283
  strategy: 'fixed',
269
284
  placement: this.placement,
270
- middleware: [offset(CatDropdown.OFFSET), flip(), shift(), ...resize]
285
+ middleware: [offset(CatDropdown.OFFSET), ...middleware, ...resize]
271
286
  }).then(({ x, y, placement }) => {
272
287
  this.content.dataset.placement = placement;
273
288
  Object.assign(this.content.style, {
@@ -1 +1 @@
1
- {"version":3,"file":"cat-dropdown.js","sourceRoot":"","sources":["../../../src/components/cat-dropdown/cat-dropdown.tsx"],"names":[],"mappings":"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","sourcesContent":["import { autoUpdate, computePosition, flip, offset, Placement, ReferenceElement, shift, size } from '@floating-ui/dom';\nimport { timeTransitionS } from '@haiilo/catalyst-tokens';\nimport { Component, Event, EventEmitter, h, Host, Listen, Method, Prop } from '@stencil/core';\nimport * as focusTrap from 'focus-trap';\nimport type { FocusableElement } from 'tabbable';\nimport firstTabbable from '../../utils/first-tabbable';\nimport findFirstTabbableIncludeHidden from '../../utils/first-tabbable-with-visibility-hidden';\n\nlet nextUniqueId = 0;\n\n/**\n * A dropdown component to display a list of actions in a dropdown menu or to\n * show additional content on demand.\n */\n@Component({\n tag: 'cat-dropdown',\n styleUrl: 'cat-dropdown.scss',\n shadow: true\n})\nexport class CatDropdown {\n private static readonly OFFSET = 4;\n private readonly id = nextUniqueId++;\n private triggerSlot!: HTMLSlotElement;\n private trigger?: FocusableElement;\n private anchorSlot!: HTMLSlotElement;\n private anchor?: Element;\n private content!: HTMLElement;\n private trap?: focusTrap.FocusTrap;\n private _isOpen: boolean | null = false;\n private cleanupFloatingUi?: () => void;\n /**\n * Tracking the origin of opening the dropdown and specify if initial focus should be set.\n * Currently we set it only when the origin is keyboard.\n * We might not need to track this in future when focus-visible support is improved across browsers\n */\n private hasInitialFocus = false;\n\n /**\n * The placement of the dropdown.\n */\n @Prop() placement: Placement = 'bottom-start';\n\n /**\n * Make the dropdown match the width of the reference regardless of its\n * contents. Note that this only applies to the minimum width of the\n * dropdown. The maximum width is still limited by the viewport.\n */\n @Prop() justify = false;\n\n /**\n * Do not close the dropdown on outside clicks.\n */\n @Prop() noAutoClose = false;\n\n /**\n * Do not navigate focus inside the dropdown via vertical arrow keys.\n */\n @Prop() arrowNavigation: 'horizontal' | 'vertical' | 'none' = 'vertical';\n\n /**\n * Do not change the size of the dropdown to ensure it isn’t too big to fit\n * in the viewport (or more specifically, its clipping context).\n */\n @Prop() noResize = false;\n\n /**\n * Allow overflow when dropdown is open.\n */\n @Prop() overflow = false;\n\n /**\n * No element in dropdown will receive focus when dropdown is open.\n * By default, the first element in tab order will receive a focus.\n * @deprecated\n * Using noInitialFocus property would be a bad practice from a11y perspective.\n * We always want visible focus to jump inside the dropdown when user uses keyboard and noInitialFocus allows to turn it off which might introduce a bug.\n * hasInitialFocus should resolve the cause of the original problem instead.\n */\n @Prop() noInitialFocus = false;\n\n /**\n * Whether the dropdown is open.\n * @readonly\n */\n @Prop() get isOpen(): boolean {\n return this._isOpen ?? false;\n }\n\n /**\n * Trigger element will not receive focus when dropdown is closed.\n */\n @Prop() noReturnFocus = false;\n\n /**\n * Whether the dropdown trigger should be initialized only before first opening.\n * Can be useful when trigger is rendered dynamically.\n */\n @Prop() delayedTriggerInit = false;\n\n /**\n * Emitted when the dropdown is opened.\n */\n @Event() catOpen!: EventEmitter<FocusEvent>;\n\n /**\n * Emitted when the dropdown is closed.\n */\n @Event() catClose!: EventEmitter<FocusEvent>;\n\n @Listen('catClick')\n clickHandler(event: CustomEvent<MouseEvent>) {\n if (!this.trigger && this.delayedTriggerInit) {\n this.hasInitialFocus = this.isEventOriginFromKeyboard(event.detail);\n this.initTrigger();\n this.toggle();\n }\n\n // hide dropdown on button clicks inside the dropdown content\n const path = event.composedPath();\n if (\n !this.noAutoClose &&\n // check if click was inside of the dropdown content\n path.includes(this.content) &&\n // check if click was not on a trigger for a sub-dropdown\n (event.target as Element)?.slot !== 'trigger' &&\n // check if click was not an element marked with data-dropdown-no-close\n !path.slice(0, path.indexOf(this.content)).find(el => this.hasAttribute(el, 'data-dropdown-no-close'))\n ) {\n this.close();\n }\n }\n\n /**\n * Toggles the dropdown.\n */\n @Method()\n async toggle(): Promise<void> {\n this._isOpen ? this.close() : this.open();\n }\n\n /**\n * Opens the dropdown.\n * @param isFocusVisible is dropdown should receive visible focus when it's opened.\n */\n @Method()\n async open(isFocusVisible?: boolean): Promise<void> {\n if (!this.trigger && this.delayedTriggerInit) {\n this.initTrigger();\n }\n\n if (this.isOpen === null || this.isOpen) {\n return; // busy or open\n }\n\n this._isOpen = null;\n this.content.style.display = 'block';\n this.hasInitialFocus = isFocusVisible ?? this.hasInitialFocus;\n\n const trigger = this.anchor || this.trigger;\n if (trigger) {\n this.cleanupFloatingUi = autoUpdate(trigger, this.content, () => this.update(trigger));\n }\n // give CSS transition time to apply\n setTimeout(() => {\n this._isOpen = true;\n this.content.classList.add('show');\n this.trigger?.setAttribute('aria-expanded', 'true');\n this.trap = this.trap\n ? this.trap.updateContainerElements(this.content)\n : focusTrap.createFocusTrap(this.content, {\n tabbableOptions: {\n getShadowRoot: true\n },\n allowOutsideClick: true,\n clickOutsideDeactivates: event =>\n !this.noAutoClose &&\n // check if click was outside of the dropdown content\n !event.composedPath().includes(this.content) &&\n // check if click was not on an element marked with data-dropdown-no-close\n !event.composedPath().find(el => this.hasAttribute(el, 'data-dropdown-no-close')),\n onPostDeactivate: () => this.close(),\n onPostActivate: () => this.catOpen.emit(),\n setReturnFocus: elem => (this.noReturnFocus ? false : this.trigger || elem),\n isKeyForward: event => {\n if (\n (this.arrowNavigation === 'horizontal' && event.key === 'ArrowRight') ||\n (this.arrowNavigation === 'vertical' && event.key === 'ArrowDown')\n ) {\n event.preventDefault();\n return true;\n }\n return event.key === 'Tab';\n },\n isKeyBackward: event => {\n if (\n (this.arrowNavigation === 'horizontal' && event.key === 'ArrowLeft') ||\n (this.arrowNavigation === 'vertical' && event.key === 'ArrowUp')\n ) {\n event.preventDefault();\n return true;\n }\n return event.key === 'Tab' && event.shiftKey;\n },\n initialFocus: () => {\n return this.hasInitialFocus && !this.noInitialFocus ? undefined : false;\n }\n });\n this.trap.activate();\n });\n }\n\n /**\n * Closes the dropdown.\n */\n @Method()\n async close(): Promise<void> {\n if (!this._isOpen) {\n return; // busy or closed\n }\n\n this._isOpen = null;\n this.trap?.deactivate();\n this.trap = undefined;\n this.content.classList.remove('show');\n // give CSS transition time to apply\n setTimeout(() => {\n this._isOpen = false;\n this.content.classList.remove('show');\n this.content.style.display = '';\n this.trigger?.setAttribute('aria-expanded', 'false');\n this.cleanupFloatingUi?.();\n this.cleanupFloatingUi = undefined;\n this.catClose.emit();\n }, timeTransitionS);\n }\n\n componentDidLoad() {\n this.initAnchor();\n if (!this.delayedTriggerInit) {\n this.initTrigger();\n }\n }\n\n disconnectedCallback() {\n this.trap?.deactivate();\n this.trap = undefined;\n this.cleanupFloatingUi?.();\n this.cleanupFloatingUi = undefined;\n }\n\n render() {\n return (\n <Host>\n <slot name=\"anchor\" ref={el => (this.anchorSlot = el as HTMLSlotElement)}></slot>\n <slot name=\"trigger\" ref={el => (this.triggerSlot = el as HTMLSlotElement)}></slot>\n <div\n id={this.contentId}\n class={{ content: true, 'overflow-auto': !this.overflow, justified: this.justify, aligned: !this.justify }}\n ref={el => (this.content = el as HTMLElement)}\n >\n <slot name=\"content\"></slot>\n </div>\n </Host>\n );\n }\n\n private get contentId() {\n return `cat-dropdown-${this.id}`;\n }\n\n private initTrigger() {\n this.trigger = this.findTrigger();\n const ariaHaspopup = this.trigger.getAttribute('aria-haspopup');\n this.trigger.setAttribute('aria-haspopup', ariaHaspopup ?? 'true');\n this.trigger.setAttribute('aria-expanded', 'false');\n this.trigger.setAttribute('aria-controls', this.contentId);\n this.trigger.addEventListener('click', (event: Event) => {\n this.hasInitialFocus = this.isEventOriginFromKeyboard(event as UIEvent);\n this.toggle();\n });\n }\n\n private isEventOriginFromKeyboard(event: UIEvent): boolean {\n return event.detail === 0;\n }\n\n private initAnchor() {\n this.anchor = (this.anchorSlot?.assignedElements?.() || [])[0];\n }\n\n private findTrigger() {\n let trigger: FocusableElement | undefined;\n let elems = this.triggerSlot?.assignedElements?.() || [];\n while (!trigger && elems.length) {\n const elem = elems.shift();\n trigger = elem?.hasAttribute('data-trigger')\n ? (elem as HTMLElement)\n : (elem?.querySelector('[data-trigger]') ?? undefined);\n }\n if (!trigger) {\n trigger = firstTabbable(this.triggerSlot);\n }\n // if no tabbable element is still found let's attempt to search through elements with visibility:hidden styles\n // which stencil assigns to component in prehydration state\n if (!trigger) {\n elems = this.triggerSlot?.assignedElements?.() || [];\n while (!trigger && elems.length) {\n const elem = elems.shift();\n trigger = findFirstTabbableIncludeHidden(elem as HTMLElement);\n }\n }\n if (!trigger) {\n throw new Error('Cannot find tabbable element. Use [data-trigger] to set the trigger.');\n }\n return trigger;\n }\n\n private update(anchorElement: ReferenceElement | undefined, justify = this.justify) {\n if (anchorElement) {\n const resize = this.noResize\n ? []\n : [\n size({\n padding: CatDropdown.OFFSET,\n apply({ rects, availableWidth, availableHeight, elements }) {\n if (justify) {\n Object.assign(elements.floating.style, {\n minWidth: `${rects.reference.width}px`,\n maxWidth: `${rects.reference.width}px`,\n maxHeight: `${availableHeight}px`\n });\n } else {\n Object.assign(elements.floating.style, {\n maxWidth: `${availableWidth}px`,\n maxHeight: `${availableHeight}px`\n });\n }\n }\n })\n ];\n computePosition(anchorElement, this.content, {\n strategy: 'fixed',\n placement: this.placement,\n middleware: [offset(CatDropdown.OFFSET), flip(), shift(), ...resize]\n }).then(({ x, y, placement }) => {\n this.content.dataset.placement = placement;\n Object.assign(this.content.style, {\n left: `${x}px`,\n top: `${y}px`\n });\n });\n }\n }\n\n private hasAttribute(elem: EventTarget, attr: string) {\n return elem instanceof HTMLElement && elem.hasAttribute(attr);\n }\n}\n"]}
1
+ {"version":3,"file":"cat-dropdown.js","sourceRoot":"","sources":["../../../src/components/cat-dropdown/cat-dropdown.tsx"],"names":[],"mappings":"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","sourcesContent":["import { autoUpdate, computePosition, flip, offset, Placement, ReferenceElement, shift, size } from '@floating-ui/dom';\nimport { timeTransitionS } from '@haiilo/catalyst-tokens';\nimport { Component, Event, EventEmitter, h, Host, Listen, Method, Prop } from '@stencil/core';\nimport * as focusTrap from 'focus-trap';\nimport type { FocusableElement } from 'tabbable';\nimport firstTabbable from '../../utils/first-tabbable';\nimport findFirstTabbableIncludeHidden from '../../utils/first-tabbable-with-visibility-hidden';\n\nlet nextUniqueId = 0;\n\n/**\n * A dropdown component to display a list of actions in a dropdown menu or to\n * show additional content on demand.\n */\n@Component({\n tag: 'cat-dropdown',\n styleUrl: 'cat-dropdown.scss',\n shadow: true\n})\nexport class CatDropdown {\n private static readonly OFFSET = 4;\n private readonly id = nextUniqueId++;\n private triggerSlot!: HTMLSlotElement;\n private trigger?: FocusableElement;\n private anchorSlot!: HTMLSlotElement;\n private anchor?: Element;\n private content!: HTMLElement;\n private trap?: focusTrap.FocusTrap;\n private _isOpen: boolean | null = false;\n private cleanupFloatingUi?: () => void;\n /**\n * Tracking the origin of opening the dropdown and specify if initial focus should be set.\n * Currently we set it only when the origin is keyboard.\n * We might not need to track this in future when focus-visible support is improved across browsers\n */\n private hasInitialFocus = false;\n\n /**\n * The placement of the dropdown.\n */\n @Prop() placement: Placement = 'bottom-start';\n\n /**\n * Make the dropdown match the width of the reference regardless of its\n * contents. Note that this only applies to the minimum width of the\n * dropdown. The maximum width is still limited by the viewport.\n */\n @Prop() justify = false;\n\n /**\n * Do not close the dropdown on outside clicks.\n */\n @Prop() noAutoClose = false;\n\n /**\n * Do not navigate focus inside the dropdown via vertical arrow keys.\n */\n @Prop() arrowNavigation: 'horizontal' | 'vertical' | 'none' = 'vertical';\n\n /**\n * Do not change the size of the dropdown to ensure it isn’t too big to fit\n * in the viewport (or more specifically, its clipping context).\n */\n @Prop() noResize = false;\n\n /**\n * Allow overflow when dropdown is open.\n */\n @Prop() overflow = false;\n\n /**\n * No element in dropdown will receive focus when dropdown is open.\n * By default, the first element in tab order will receive a focus.\n * @deprecated\n * Using noInitialFocus property would be a bad practice from a11y perspective.\n * We always want visible focus to jump inside the dropdown when user uses keyboard and noInitialFocus allows to turn it off which might introduce a bug.\n * hasInitialFocus should resolve the cause of the original problem instead.\n */\n @Prop() noInitialFocus = false;\n\n /**\n * Whether the dropdown is open.\n * @readonly\n */\n @Prop() get isOpen(): boolean {\n return this._isOpen ?? false;\n }\n\n /**\n * Trigger element will not receive focus when dropdown is closed.\n */\n @Prop() noReturnFocus = false;\n\n /**\n * Whether the dropdown trigger should be initialized only before first opening.\n * Can be useful when trigger is rendered dynamically.\n */\n @Prop() delayedTriggerInit = false;\n\n /**\n * Emitted when the dropdown is opened.\n */\n @Event() catOpen!: EventEmitter<FocusEvent>;\n\n /**\n * Emitted when the dropdown is closed.\n */\n @Event() catClose!: EventEmitter<FocusEvent>;\n\n @Listen('catClick')\n clickHandler(event: CustomEvent<MouseEvent>) {\n if (!this.trigger && this.delayedTriggerInit) {\n this.hasInitialFocus = this.isEventOriginFromKeyboard(event.detail);\n this.initTrigger();\n this.toggle();\n }\n\n // hide dropdown on button clicks inside the dropdown content\n const path = event.composedPath();\n if (\n !this.noAutoClose &&\n // check if click was inside of the dropdown content\n path.includes(this.content) &&\n // check if click was not on a trigger for a sub-dropdown\n (event.target as Element)?.slot !== 'trigger' &&\n // check if click was not an element marked with data-dropdown-no-close\n !path.slice(0, path.indexOf(this.content)).find(el => this.hasAttribute(el, 'data-dropdown-no-close'))\n ) {\n this.close();\n }\n }\n\n /**\n * Toggles the dropdown.\n */\n @Method()\n async toggle(): Promise<void> {\n this._isOpen ? this.close() : this.open();\n }\n\n /**\n * Opens the dropdown.\n * @param isFocusVisible is dropdown should receive visible focus when it's opened.\n */\n @Method()\n async open(isFocusVisible?: boolean): Promise<void> {\n if (!this.trigger && this.delayedTriggerInit) {\n this.initTrigger();\n }\n\n if (this.isOpen === null || this.isOpen) {\n return; // busy or open\n }\n\n this._isOpen = null;\n this.content.style.display = 'block';\n this.hasInitialFocus = isFocusVisible ?? this.hasInitialFocus;\n\n const trigger = this.anchor || this.trigger;\n if (trigger) {\n this.cleanupFloatingUi = autoUpdate(trigger, this.content, () => this.update(trigger));\n }\n // give CSS transition time to apply\n setTimeout(() => {\n this._isOpen = true;\n this.content.classList.add('show');\n this.trigger?.setAttribute('aria-expanded', 'true');\n this.trap = this.trap\n ? this.trap.updateContainerElements(this.content)\n : focusTrap.createFocusTrap(this.content, {\n tabbableOptions: {\n getShadowRoot: true\n },\n allowOutsideClick: true,\n clickOutsideDeactivates: event =>\n !this.noAutoClose &&\n // check if click was outside of the dropdown content\n !event.composedPath().includes(this.content) &&\n // check if click was not on an element marked with data-dropdown-no-close\n !event.composedPath().find(el => this.hasAttribute(el, 'data-dropdown-no-close')),\n onPostDeactivate: () => this.close(),\n onPostActivate: () => this.catOpen.emit(),\n setReturnFocus: elem => (this.noReturnFocus ? false : this.trigger || elem),\n isKeyForward: event => {\n if (\n (this.arrowNavigation === 'horizontal' && event.key === 'ArrowRight') ||\n (this.arrowNavigation === 'vertical' && event.key === 'ArrowDown')\n ) {\n event.preventDefault();\n return true;\n }\n return event.key === 'Tab';\n },\n isKeyBackward: event => {\n if (\n (this.arrowNavigation === 'horizontal' && event.key === 'ArrowLeft') ||\n (this.arrowNavigation === 'vertical' && event.key === 'ArrowUp')\n ) {\n event.preventDefault();\n return true;\n }\n return event.key === 'Tab' && event.shiftKey;\n },\n initialFocus: () => {\n return this.hasInitialFocus && !this.noInitialFocus ? undefined : false;\n }\n });\n this.trap.activate();\n });\n }\n\n /**\n * Closes the dropdown.\n */\n @Method()\n async close(): Promise<void> {\n if (!this._isOpen) {\n return; // busy or closed\n }\n\n this._isOpen = null;\n this.trap?.deactivate();\n this.trap = undefined;\n this.content.classList.remove('show');\n // give CSS transition time to apply\n setTimeout(() => {\n this._isOpen = false;\n this.content.classList.remove('show');\n this.content.style.display = '';\n this.trigger?.setAttribute('aria-expanded', 'false');\n this.cleanupFloatingUi?.();\n this.cleanupFloatingUi = undefined;\n this.catClose.emit();\n }, timeTransitionS);\n }\n\n componentDidLoad() {\n this.initAnchor();\n if (!this.delayedTriggerInit) {\n this.initTrigger();\n }\n }\n\n disconnectedCallback() {\n this.trap?.deactivate();\n this.trap = undefined;\n this.cleanupFloatingUi?.();\n this.cleanupFloatingUi = undefined;\n }\n\n render() {\n return (\n <Host>\n <slot name=\"anchor\" ref={el => (this.anchorSlot = el as HTMLSlotElement)}></slot>\n <slot name=\"trigger\" ref={el => (this.triggerSlot = el as HTMLSlotElement)}></slot>\n <div\n id={this.contentId}\n class={{ content: true, 'overflow-auto': !this.overflow, justified: this.justify, aligned: !this.justify }}\n ref={el => (this.content = el as HTMLElement)}\n >\n <slot name=\"content\"></slot>\n </div>\n </Host>\n );\n }\n\n private get contentId() {\n return `cat-dropdown-${this.id}`;\n }\n\n private initTrigger() {\n this.trigger = this.findTrigger();\n const ariaHaspopup = this.trigger.getAttribute('aria-haspopup');\n this.trigger.setAttribute('aria-haspopup', ariaHaspopup ?? 'true');\n this.trigger.setAttribute('aria-expanded', 'false');\n this.trigger.setAttribute('aria-controls', this.contentId);\n this.trigger.addEventListener('click', (event: Event) => {\n this.hasInitialFocus = this.isEventOriginFromKeyboard(event as UIEvent);\n this.toggle();\n });\n }\n\n private isEventOriginFromKeyboard(event: UIEvent): boolean {\n return event.detail === 0;\n }\n\n private initAnchor() {\n this.anchor = (this.anchorSlot?.assignedElements?.() || [])[0];\n }\n\n private findTrigger() {\n let trigger: FocusableElement | undefined;\n let elems = this.triggerSlot?.assignedElements?.() || [];\n while (!trigger && elems.length) {\n const elem = elems.shift();\n trigger = elem?.hasAttribute('data-trigger')\n ? (elem as HTMLElement)\n : (elem?.querySelector('[data-trigger]') ?? undefined);\n }\n if (!trigger) {\n trigger = firstTabbable(this.triggerSlot);\n }\n // if no tabbable element is still found let's attempt to search through elements with visibility:hidden styles\n // which stencil assigns to component in prehydration state\n if (!trigger) {\n elems = this.triggerSlot?.assignedElements?.() || [];\n while (!trigger && elems.length) {\n const elem = elems.shift();\n trigger = findFirstTabbableIncludeHidden(elem as HTMLElement);\n }\n }\n if (!trigger) {\n throw new Error('Cannot find tabbable element. Use [data-trigger] to set the trigger.');\n }\n return trigger;\n }\n\n private update(anchorElement: ReferenceElement | undefined, justify = this.justify) {\n if (anchorElement) {\n const resize = this.noResize\n ? []\n : [\n size({\n padding: CatDropdown.OFFSET,\n apply({ rects, availableWidth, availableHeight, elements }) {\n if (justify) {\n Object.assign(elements.floating.style, {\n minWidth: `${rects.reference.width}px`,\n maxWidth: `${rects.reference.width}px`,\n maxHeight: `${availableHeight}px`\n });\n } else {\n Object.assign(elements.floating.style, {\n maxWidth: `${availableWidth}px`,\n maxHeight: `${availableHeight}px`\n });\n }\n }\n })\n ];\n const middleware = [offset(CatDropdown.OFFSET)];\n const flipMiddleware = flip({\n // Ensure we flip to the perpendicular axis if it doesn't fit\n // on narrow viewports.\n crossAxis: 'alignment',\n fallbackAxisSideDirection: 'end'\n });\n const shiftMiddleware = shift();\n\n // Prioritize flip over shift for edge-aligned placements only.\n if (this.placement.includes('-')) {\n middleware.push(flipMiddleware, shiftMiddleware);\n } else {\n middleware.push(shiftMiddleware, flipMiddleware);\n }\n computePosition(anchorElement, this.content, {\n strategy: 'fixed',\n placement: this.placement,\n middleware: [offset(CatDropdown.OFFSET), ...middleware, ...resize]\n }).then(({ x, y, placement }) => {\n this.content.dataset.placement = placement;\n Object.assign(this.content.style, {\n left: `${x}px`,\n top: `${y}px`\n });\n });\n }\n }\n\n private hasAttribute(elem: EventTarget, attr: string) {\n return elem instanceof HTMLElement && elem.hasAttribute(attr);\n }\n}\n"]}
@@ -343,21 +343,27 @@ export class CatSelect {
343
343
  options
344
344
  });
345
345
  });
346
+ this.renderSubscription?.unsubscribe();
347
+ if (connector.renderOptions$) {
348
+ this.renderSubscription = connector.renderOptions$.subscribe(() => {
349
+ this.rerenderOptions();
350
+ });
351
+ }
346
352
  }
347
353
  render() {
348
354
  this.hostElement.tabIndex = Number(this.hostElement.getAttribute('tabindex')) || 0;
349
- return (h(Host, { key: '044a13b28c3c3d3fcb5b06efa53d489783ae9698' }, h("div", { key: 'b540d0b58849b8b401c611dfa08da42f45a7953c', class: {
355
+ return (h(Host, { key: '7489b4123c900ebefa06dcebde32b0a4ee52d4a3' }, h("div", { key: '9669441806e8bebc5f583957cc1a24330f06085a', class: {
350
356
  'select-field': true,
351
357
  'select-horizontal': this.horizontal ?? this.fallbackHorizontal ?? false,
352
358
  'select-multiple': this.multiple
353
- } }, h("div", { key: '3864749c06c0aa54df1912f90636094dcdd4a229', class: { 'label-container': true, hidden: this.labelHidden } }, (this.hasSlottedLabel || this.label) && (h("label", { key: 'b2e64f375a8d2e9430007b548f468055a1a83b9b', htmlFor: `select-${this.id}-input`, part: "label" }, h("span", { key: '1d09f458ed23045ecbd3ca3b9bb2fa5740f6c4e1', class: "label-wrapper" }, (this.hasSlottedLabel && h("slot", { key: '7c569d0f97e2c48d6515e051dd8098003b0dc2c2', name: "label" })) || this.label, h("div", { key: 'f3c8709ea17c26d65e41ceb505af51dac81dda37', class: "label-metadata" }, !this.required && (this.requiredMarker ?? 'optional').startsWith('optional') && (h("span", { key: 'f2cc0d4a5fd0d815a1087b7f2b1c55c73ca36e93', class: "label-optional", "aria-hidden": "true" }, "(", i18n.t('input.optional'), ")")), this.required && this.requiredMarker?.startsWith('required') && (h("span", { key: 'beb3aaaf8261978be7895a1580a42f25f65ef5e7', class: "label-optional", "aria-hidden": "true" }, "(", i18n.t('input.required'), ")"))))))), h("div", { key: '23a30b437dca6aea6d6f01156dc6c56faae3912f', class: "select-container" }, h("div", { key: '146509fd8146b3afa9c5157c7a37198c810330d7', class: { 'select-wrapper': true, 'select-disabled': this.disabled, 'select-invalid': this.invalid }, ref: el => (this.trigger = el), id: this.id, role: "combobox", "aria-expanded": this.state.isOpen || this.isPillboxActive(), "aria-controls": this.isPillboxActive() ? `select-pillbox-${this.id}` : `select-listbox-${this.id}`, "aria-required": this.required ? 'true' : false, "aria-activedescendant": this.activeDescendant, onClick: e => this.onClick(e) }, h("div", { key: 'f9f8b2cc0914ba4a7151c580f9e9eda332aad35e', class: "select-wrapper-inner" }, this.multiple && this.state.selection.length ? (h("div", { id: `select-pillbox-${this.id}`, role: "listbox", "aria-orientation": "horizontal", class: "select-pills" }, this.state.selection.map((item, i) => (h("span", { class: {
359
+ } }, h("div", { key: 'a94a2217157c125e34802b140843d2fffd63283f', class: { 'label-container': true, hidden: this.labelHidden } }, (this.hasSlottedLabel || this.label) && (h("label", { key: '557e2754156cb4484972dcccca103451db00a01e', htmlFor: `select-${this.id}-input`, part: "label" }, h("span", { key: '8d229578a218717dbe78a63e416cba36cc300c37', class: "label-wrapper" }, (this.hasSlottedLabel && h("slot", { key: 'f1700687e21b73edce905bc8325479bed8c31962', name: "label" })) || this.label, h("div", { key: '109009794bab604eca5d3f690858145ac770ea81', class: "label-metadata" }, !this.required && (this.requiredMarker ?? 'optional').startsWith('optional') && (h("span", { key: '5868ecd309ab485a60439fd6743be56947f9d43e', class: "label-optional", "aria-hidden": "true" }, "(", i18n.t('input.optional'), ")")), this.required && this.requiredMarker?.startsWith('required') && (h("span", { key: '8e61a17e1d1b9f3fc584c08824b243b5f0c07c0f', class: "label-optional", "aria-hidden": "true" }, "(", i18n.t('input.required'), ")"))))))), h("div", { key: '9d211cd7674cda6f9bcfeebaf1252055239421ce', class: "select-container" }, h("div", { key: '878137436714dff589d4731ada14d11e443ab4a6', class: { 'select-wrapper': true, 'select-disabled': this.disabled, 'select-invalid': this.invalid }, ref: el => (this.trigger = el), id: this.id, role: "combobox", "aria-expanded": this.state.isOpen || this.isPillboxActive(), "aria-controls": this.isPillboxActive() ? `select-pillbox-${this.id}` : `select-listbox-${this.id}`, "aria-required": this.required ? 'true' : false, "aria-activedescendant": this.activeDescendant, onClick: e => this.onClick(e) }, h("div", { key: '7a268001a9bc895aa5fd1157a57f89555ad9e868', class: "select-wrapper-inner" }, this.multiple && this.state.selection.length ? (h("div", { id: `select-pillbox-${this.id}`, role: "listbox", "aria-orientation": "horizontal", class: "select-pills" }, this.state.selection.map((item, i) => (h("span", { class: {
354
360
  pill: true,
355
361
  'select-no-open': true,
356
362
  'select-option-active': this.state.activeSelectionIndex === i
357
- }, role: "option", "aria-selected": "true", id: `select-${this.id}-selection-${i}` }, item.render.avatar ? (h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, icon: item.render.avatar.icon, initials: item.render.avatar.initials ?? '' })) : null, h("span", null, item.render.label), !this.disabled && (h("cat-button", { size: "xs", variant: "text", icon: "$cat:select-clear", iconOnly: true, a11yLabel: i18n.t('select.deselect'), onClick: () => this.deselect(item.item.id), tabIndex: -1, "data-dropdown-no-close": true }))))))) : this.state.selection.length && this.state.selection[0].render.avatar ? (h("cat-avatar", { label: this.state.selection[0].render.label, round: this.state.selection[0].render.avatar.round, src: this.state.selection[0].render.avatar.src, icon: this.state.selection[0].render.avatar.icon, initials: this.state.selection[0].render.avatar.initials ?? '' })) : null, h("input", { key: 'ccf158ead3c32c1376744366ccae13d32762e150', "data-test": this.testId, ...this.nativeAttributes, part: "input", id: `select-${this.id}-input`, class: "select-input", role: "combobox", ref: el => (this.input = el), "aria-controls": this.isPillboxActive() ? `select-pillbox-${this.id}` : `select-listbox-${this.id}`, "aria-activedescendant": this.activeDescendant, "aria-invalid": this.invalid ? 'true' : undefined, "aria-describedby": this.hasHint ? this.id + '-hint' : undefined, "aria-autocomplete": "list", onInput: this.onInput.bind(this), value: !this.multiple ? this.state.term : undefined, placeholder: this.placeholder, disabled: this.disabled || this.state.isResolving })), this.state.isResolving && h("cat-spinner", { key: '8af750f50e620a73f9a35c66708293e758a2786e' }), this.invalid && (h("cat-icon", { key: '114ead7c9b473945a1fb2f5774e74d75c57819f5', icon: "$cat:input-error", class: "icon-suffix cat-text-danger", size: "l" })), (this.state.selection.length || this.state.term.length) &&
363
+ }, role: "option", "aria-selected": "true", id: `select-${this.id}-selection-${i}` }, item.render.avatar ? (h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, icon: item.render.avatar.icon, initials: item.render.avatar.initials ?? '' })) : null, h("span", null, item.render.label), !this.disabled && (h("cat-button", { size: "xs", variant: "text", icon: "$cat:select-clear", iconOnly: true, a11yLabel: i18n.t('select.deselect'), onClick: () => this.deselect(item.item.id), tabIndex: -1, "data-dropdown-no-close": true }))))))) : this.state.selection.length && this.state.selection[0].render.avatar ? (h("cat-avatar", { label: this.state.selection[0].render.label, round: this.state.selection[0].render.avatar.round, src: this.state.selection[0].render.avatar.src, icon: this.state.selection[0].render.avatar.icon, initials: this.state.selection[0].render.avatar.initials ?? '' })) : null, h("input", { key: 'dd9c6f767f5cfc9c2e3e0f37dd4bad075f1169c8', "data-test": this.testId, ...this.nativeAttributes, part: "input", id: `select-${this.id}-input`, class: "select-input", role: "combobox", ref: el => (this.input = el), "aria-controls": this.isPillboxActive() ? `select-pillbox-${this.id}` : `select-listbox-${this.id}`, "aria-activedescendant": this.activeDescendant, "aria-invalid": this.invalid ? 'true' : undefined, "aria-describedby": this.hasHint ? this.id + '-hint' : undefined, "aria-autocomplete": "list", onInput: this.onInput.bind(this), value: !this.multiple ? this.state.term : undefined, placeholder: this.placeholder, disabled: this.disabled || this.state.isResolving })), this.state.isResolving && h("cat-spinner", { key: 'c3ed10971f8f29d352df71a5bb577ff3f4499ccd' }), this.invalid && (h("cat-icon", { key: 'c4788a44a097252f58c43769edec339c57ed74e4', icon: "$cat:input-error", class: "icon-suffix cat-text-danger", size: "l" })), (this.state.selection.length || this.state.term.length) &&
358
364
  !this.disabled &&
359
365
  !this.state.isResolving &&
360
- this.clearable ? (h("cat-button", { id: `select-clear-btn-${this.id}`, iconOnly: true, icon: "$cat:input-close", variant: "text", size: "s", a11yLabel: i18n.t('input.clear'), onCatClick: () => this.clearInput(), "data-dropdown-no-close": true })) : null, !this.state.isResolving && (h("cat-button", { key: 'ece4331f89cbb9c37d9f9693800bca1320ff7f37', iconOnly: true, icon: "$cat:select-open", class: { 'select-btn': true, 'select-btn-open': this.state.isOpen }, variant: "text", size: "s", a11yLabel: this.state.isOpen ? i18n.t('select.close') : i18n.t('select.open'), "aria-controls": `select-listbox-${this.id}`, "aria-expanded": this.state.isOpen, tabIndex: -1, disabled: this.disabled || this.state.isResolving, "data-dropdown-no-close": true }))), this.hasHint && (h(CatFormHint, { key: 'd25455be1db5404a698b35d088ba0a303215a321', id: this.id, hint: this.hint, slottedHint: this.hasSlottedHint && h("slot", { name: "hint" }), errorMap: this.errorMap })))), h("div", { key: 'c58c1914f90b0fb9a7b40c4c37e2fe7d92877ab8', class: "select-dropdown", ref: el => (this.dropdown = el), style: { display: this.state.isOpen ? 'block' : undefined } }, this.state.isOpen && (h("cat-scrollable", { key: '73a6a048ba31d8f5944d4a1aa6c8c4fb96e56df2', class: "select-options-wrapper", scrolledBuffer: 56, noOverflowX: true, noOverscroll: true, noScrolledInit: true, onScrolledBottom: () => this.more$.next() }, h("ul", { key: '4b86961480022fd7dd0e1641fdaed8116e320090', class: "select-options", role: "listbox", "aria-multiselectable": this.multiple, "aria-setsize": this.state.totalElements, id: `select-listbox-${this.id}` }, this.optionsList, this.state.isFirstLoading
366
+ this.clearable ? (h("cat-button", { id: `select-clear-btn-${this.id}`, iconOnly: true, icon: "$cat:input-close", variant: "text", size: "s", a11yLabel: i18n.t('input.clear'), onCatClick: () => this.clearInput(), "data-dropdown-no-close": true })) : null, !this.state.isResolving && (h("cat-button", { key: 'a1ae4dfc03feec1a556f818ea08ba8a53b10f132', iconOnly: true, icon: "$cat:select-open", class: { 'select-btn': true, 'select-btn-open': this.state.isOpen }, variant: "text", size: "s", a11yLabel: this.state.isOpen ? i18n.t('select.close') : i18n.t('select.open'), "aria-controls": `select-listbox-${this.id}`, "aria-expanded": this.state.isOpen, tabIndex: -1, disabled: this.disabled || this.state.isResolving, "data-dropdown-no-close": true }))), this.hasHint && (h(CatFormHint, { key: '2557e44ce584d96cc8497cee27d8e6e8f6464fd9', id: this.id, hint: this.hint, slottedHint: this.hasSlottedHint && h("slot", { name: "hint" }), errorMap: this.errorMap })))), h("div", { key: '795de862359d06464591e32d3a410a8974a55028', class: "select-dropdown", ref: el => (this.dropdown = el), style: { display: this.state.isOpen ? 'block' : undefined } }, this.state.isOpen && (h("cat-scrollable", { key: 'b88fc1b204533e3714b8533c10b7a817fe2d4ef1', class: "select-options-wrapper", scrolledBuffer: 56, noOverflowX: true, noOverscroll: true, noScrolledInit: true, onScrolledBottom: () => this.more$.next() }, h("ul", { key: 'f0fe6e0c398c7682363174ec6e9f04eaa8e25073', class: "select-options", role: "listbox", "aria-multiselectable": this.multiple, "aria-setsize": this.state.totalElements, id: `select-listbox-${this.id}` }, this.optionsList, this.state.isFirstLoading
361
367
  ? Array.from(Array(CatSelect.SKELETON_COUNT)).map(() => (h("li", { class: "select-option-loading" }, h("cat-skeleton", { variant: "body", lines: 1 }), h("cat-skeleton", { variant: "body", lines: 1 }))))
362
368
  : !this.state.options.length &&
363
369
  !this.tags && (h("li", { class: "select-option-empty" }, this.noItems ? this.noItems : i18n.t('select.empty')))))))));
@@ -381,7 +387,7 @@ export class CatSelect {
381
387
  return (h("li", { role: "option", class: "select-option", id: `select-${this.id}-option-${i}`, "aria-selected": isOptionSelected ? 'true' : 'false' }, this.multiple ? (h("cat-checkbox", { class: { 'select-option-active': this.state.activeOptionIndex === i }, checked: isOptionSelected, tabIndex: -1, labelLeft: true, onFocus: () => this.input?.focus(), onCatChange: e => {
382
388
  !isTagOption ? this.toggle(item) : this.toggleTag(item);
383
389
  e.stopPropagation();
384
- } }, h("span", { slot: "label", class: "select-option-inner" }, item.render.avatar ? (h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, icon: item.render.avatar.icon, initials: item.render.avatar.initials ?? '' })) : null, h("span", { class: "select-option-text" }, h("span", { class: "select-option-label" }, getLabel()), h("span", { class: "select-option-description" }, item.render.description))))) : (h("div", { class: {
390
+ } }, h("span", { slot: "label", class: "select-option-inner" }, item.render.avatar ? (h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, icon: item.render.avatar.icon, initials: item.render.avatar.initials ?? '' })) : null, h("span", { class: "select-option-text", part: "option" }, h("span", { class: "select-option-label" }, getLabel()), h("span", { class: "select-option-description" }, item.render.description))))) : (h("div", { class: {
385
391
  'select-option-inner': true,
386
392
  'select-option-single': true,
387
393
  'select-option-active': this.state.activeOptionIndex === i
@@ -479,6 +485,11 @@ export class CatSelect {
479
485
  });
480
486
  }
481
487
  }
488
+ rerenderOptions() {
489
+ const optionItems = this.state.options.map(o => o.item);
490
+ const updatedOptions = this.toSelectItems(this.connector, optionItems);
491
+ this.patchState({ options: updatedOptions });
492
+ }
482
493
  toggle(item) {
483
494
  this.isSelected(item.item.id)
484
495
  ? this.deselect(item.item.id)
@@ -500,6 +511,8 @@ export class CatSelect {
500
511
  this.connector = connector ?? this.connector;
501
512
  this.subscription?.unsubscribe();
502
513
  this.subscription = undefined;
514
+ this.renderSubscription?.unsubscribe();
515
+ this.renderSubscription = undefined;
503
516
  this.state = INIT_STATE;
504
517
  }
505
518
  onClick(event) {