@ionic/core 8.8.7-dev.11778599050.191a48e3 → 8.8.7-dev.11778680417.1f9234bd
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/components/ion-action-sheet.js +1 -1
- package/components/ion-alert.js +1 -1
- package/components/ion-back-button.js +1 -1
- package/components/ion-button.js +1 -1
- package/components/ion-card.js +1 -1
- package/components/ion-chip.js +1 -1
- package/components/ion-col.js +1 -1
- package/components/ion-datetime-button.js +1 -1
- package/components/ion-datetime.js +1 -1
- package/components/ion-fab-button.js +1 -1
- package/components/ion-gallery.d.ts +11 -0
- package/components/ion-gallery.js +4 -0
- package/components/ion-grid.js +1 -1
- package/components/ion-header.js +1 -1
- package/components/ion-img.js +1 -1
- package/components/ion-infinite-scroll-content.js +1 -1
- package/components/ion-infinite-scroll.js +1 -1
- package/components/ion-input-otp.js +1 -1
- package/components/ion-input-password-toggle.js +1 -1
- package/components/ion-input.js +1 -1
- package/components/ion-item-divider.js +1 -1
- package/components/ion-item-group.js +1 -1
- package/components/ion-item-option.js +1 -1
- package/components/ion-item-options.js +1 -1
- package/components/ion-item-sliding.js +1 -1
- package/components/ion-item.js +1 -1
- package/components/ion-label.js +1 -1
- package/components/ion-list-header.js +1 -1
- package/components/ion-list.js +1 -1
- package/components/ion-loading.js +1 -1
- package/components/ion-menu-button.js +1 -1
- package/components/ion-menu-toggle.js +1 -1
- package/components/ion-menu.js +1 -1
- package/components/ion-modal.js +1 -1
- package/components/ion-nav-link.js +1 -1
- package/components/ion-nav.js +1 -1
- package/components/ion-note.js +1 -1
- package/components/ion-picker-column-option.js +1 -1
- package/components/ion-picker-legacy-column.js +1 -1
- package/components/ion-picker-legacy.js +1 -1
- package/components/ion-popover.js +1 -1
- package/components/ion-progress-bar.js +1 -1
- package/components/ion-radio-group.js +1 -1
- package/components/ion-radio.js +1 -1
- package/components/ion-range.js +1 -1
- package/components/ion-refresher-content.js +1 -1
- package/components/ion-refresher.js +1 -1
- package/components/ion-reorder-group.js +1 -1
- package/components/ion-reorder.js +1 -1
- package/components/ion-ripple-effect.js +1 -1
- package/components/ion-router-link.js +1 -1
- package/components/ion-router-outlet.js +1 -1
- package/components/ion-row.js +1 -1
- package/components/ion-searchbar.js +1 -1
- package/components/ion-segment-button.js +1 -1
- package/components/ion-segment-content.js +1 -1
- package/components/ion-segment-view.js +1 -1
- package/components/ion-segment.js +1 -1
- package/components/ion-select-modal.js +1 -1
- package/components/ion-select-option.js +1 -1
- package/components/ion-select-popover.js +1 -1
- package/components/ion-select.js +1 -1
- package/components/ion-skeleton-text.js +1 -1
- package/components/ion-spinner.js +1 -1
- package/components/ion-split-pane.js +1 -1
- package/components/ion-tab-bar.js +1 -1
- package/components/ion-tab-button.js +1 -1
- package/components/ion-tab.js +1 -1
- package/components/ion-tabs.js +1 -1
- package/components/ion-text.js +1 -1
- package/components/ion-textarea.js +1 -1
- package/components/ion-thumbnail.js +1 -1
- package/components/ion-title.js +1 -1
- package/components/ion-toast.js +1 -1
- package/components/ion-toggle.js +1 -1
- package/components/ion-toolbar.js +1 -1
- package/components/p-B2rpt1JV.js +4 -0
- package/components/p-B6zr9RZN.js +4 -0
- package/components/{p-Brxa0j7O.js → p-B71c6yUH.js} +1 -1
- package/components/{p-C2cZvGcF.js → p-BFbsici0.js} +1 -1
- package/components/{p-CoarhFWH.js → p-BLCuPAtN.js} +1 -1
- package/components/{p-GnGGIfCd.js → p-BRWWcnBq.js} +1 -1
- package/components/{p-BfHB6wX_.js → p-BXcCGjEc.js} +1 -1
- package/components/{p-BU8N7ZrK.js → p-BqImG3uk.js} +1 -1
- package/components/{p-D5lMX0xt.js → p-C8ktKu9j.js} +1 -1
- package/components/{p-BhfW3d9j.js → p-CIoAIKEr.js} +1 -1
- package/components/p-CN-WzkJE.js +4 -0
- package/components/{p-CnwZE7CW.js → p-CoFqDNc5.js} +1 -1
- package/components/{p-TpZHKDyk.js → p-DAv9P_LE.js} +1 -1
- package/components/{p-CeYwuysM.js → p-DH_9VCbD.js} +1 -1
- package/components/{p-CdYTq34D.js → p-DTtRWhIZ.js} +1 -1
- package/components/{p-C-_EGKki.js → p-DXUyXgVL.js} +1 -1
- package/components/{p-BTYqyHph.js → p-Di5rHO3q.js} +1 -1
- package/components/{p-D39cV-un.js → p-Dmuy6xyk.js} +1 -1
- package/components/{p-BtAlyZ0b.js → p-IMXp2Inn.js} +1 -1
- package/components/{p-DAeMHNER.js → p-TR4ubkPu.js} +1 -1
- package/dist/cjs/ion-app_8.cjs.entry.js +7 -7
- package/dist/cjs/ion-avatar_3.cjs.entry.js +2 -2
- package/dist/cjs/ion-col_3.cjs.entry.js +8 -6
- package/dist/cjs/ion-datetime_3.cjs.entry.js +4 -4
- package/dist/cjs/ion-gallery.cjs.entry.js +490 -0
- package/dist/cjs/ion-img.cjs.entry.js +2 -2
- package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +3 -3
- package/dist/cjs/ion-input-otp.cjs.entry.js +3 -3
- package/dist/cjs/ion-input-password-toggle.cjs.entry.js +3 -3
- package/dist/cjs/ion-input.cjs.entry.js +4 -4
- package/dist/cjs/ion-item-option_3.cjs.entry.js +4 -4
- package/dist/cjs/ion-item_8.cjs.entry.js +12 -12
- package/dist/cjs/ion-loading.cjs.entry.js +2 -2
- package/dist/cjs/ion-menu_3.cjs.entry.js +6 -6
- package/dist/cjs/ion-modal.cjs.entry.js +4 -4
- package/dist/cjs/ion-nav_2.cjs.entry.js +2 -2
- package/dist/cjs/ion-picker-column-option.cjs.entry.js +2 -2
- package/dist/cjs/ion-popover.cjs.entry.js +2 -2
- package/dist/cjs/ion-progress-bar.cjs.entry.js +1 -1
- package/dist/cjs/ion-radio_2.cjs.entry.js +5 -5
- package/dist/cjs/ion-range.cjs.entry.js +3 -3
- package/dist/cjs/ion-refresher_2.cjs.entry.js +3 -3
- package/dist/cjs/ion-reorder_2.cjs.entry.js +3 -3
- package/dist/cjs/ion-ripple-effect.cjs.entry.js +1 -1
- package/dist/cjs/ion-route_4.cjs.entry.js +2 -2
- package/dist/cjs/ion-searchbar.cjs.entry.js +4 -4
- package/dist/cjs/ion-segment-content.cjs.entry.js +1 -1
- package/dist/cjs/ion-segment-view.cjs.entry.js +2 -2
- package/dist/cjs/ion-segment_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-select-modal.cjs.entry.js +1 -1
- package/dist/cjs/ion-select_3.cjs.entry.js +6 -6
- package/dist/cjs/ion-spinner.cjs.entry.js +1 -1
- package/dist/cjs/ion-split-pane.cjs.entry.js +3 -2
- package/dist/cjs/ion-tab-bar_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-tab_2.cjs.entry.js +3 -3
- package/dist/cjs/ion-text.cjs.entry.js +2 -2
- package/dist/cjs/ion-textarea.cjs.entry.js +3 -3
- package/dist/cjs/ion-toast.cjs.entry.js +2 -2
- package/dist/cjs/ion-toggle.cjs.entry.js +3 -3
- package/dist/cjs/ionic.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/collection-manifest.json +6 -0
- package/dist/collection/components/col/col.js +3 -2
- package/dist/collection/components/gallery/gallery-constants.js +12 -0
- package/dist/collection/components/gallery/gallery-interface.js +1 -0
- package/dist/collection/components/gallery/gallery.css +100 -0
- package/dist/collection/components/gallery/gallery.js +575 -0
- package/dist/collection/components/gallery/test/utils.js +100 -0
- package/dist/collection/components/grid/grid.js +2 -2
- package/dist/collection/components/header/header.js +2 -2
- package/dist/collection/components/img/img.js +2 -2
- package/dist/collection/components/infinite-scroll/infinite-scroll.js +1 -1
- package/dist/collection/components/infinite-scroll-content/infinite-scroll-content.js +2 -2
- package/dist/collection/components/input/input.js +4 -4
- package/dist/collection/components/input-otp/input-otp.js +3 -3
- package/dist/collection/components/input-password-toggle/input-password-toggle.js +3 -3
- package/dist/collection/components/item-divider/item-divider.js +2 -2
- package/dist/collection/components/item-group/item-group.js +1 -1
- package/dist/collection/components/item-option/item-option.js +2 -2
- package/dist/collection/components/item-options/item-options.js +1 -1
- package/dist/collection/components/item-sliding/item-sliding.js +1 -1
- package/dist/collection/components/label/label.js +2 -2
- package/dist/collection/components/list/list.js +1 -1
- package/dist/collection/components/list-header/list-header.js +2 -2
- package/dist/collection/components/loading/loading.js +2 -2
- package/dist/collection/components/menu/menu.js +2 -2
- package/dist/collection/components/menu-button/menu-button.js +2 -2
- package/dist/collection/components/menu-toggle/menu-toggle.js +2 -2
- package/dist/collection/components/modal/modal.js +4 -4
- package/dist/collection/components/nav/nav.js +1 -1
- package/dist/collection/components/nav-link/nav-link.js +1 -1
- package/dist/collection/components/note/note.js +2 -2
- package/dist/collection/components/picker-column-option/picker-column-option.js +2 -2
- package/dist/collection/components/picker-legacy/picker.js +2 -2
- package/dist/collection/components/picker-legacy-column/picker-column.js +2 -2
- package/dist/collection/components/popover/popover.js +2 -2
- package/dist/collection/components/progress-bar/progress-bar.js +1 -1
- package/dist/collection/components/radio/radio.js +3 -3
- package/dist/collection/components/radio-group/radio-group.js +2 -2
- package/dist/collection/components/range/range.js +3 -3
- package/dist/collection/components/refresher/refresher.js +1 -1
- package/dist/collection/components/refresher-content/refresher-content.js +2 -2
- package/dist/collection/components/reorder/reorder.js +2 -2
- package/dist/collection/components/reorder-group/reorder-group.js +1 -1
- package/dist/collection/components/ripple-effect/ripple-effect.js +1 -1
- package/dist/collection/components/router-link/router-link.js +2 -2
- package/dist/collection/components/router-outlet/router-outlet.js +1 -1
- package/dist/collection/components/row/row.js +2 -2
- package/dist/collection/components/searchbar/searchbar.js +4 -4
- package/dist/collection/components/segment/segment.js +2 -2
- package/dist/collection/components/segment-button/segment-button.js +2 -2
- package/dist/collection/components/segment-content/segment-content.js +1 -1
- package/dist/collection/components/segment-view/segment-view.js +2 -2
- package/dist/collection/components/select/select.js +3 -3
- package/dist/collection/components/select-modal/select-modal.js +1 -1
- package/dist/collection/components/select-option/select-option.js +1 -1
- package/dist/collection/components/select-popover/select-popover.js +2 -2
- package/dist/collection/components/skeleton-text/skeleton-text.js +2 -2
- package/dist/collection/components/spinner/spinner.js +1 -1
- package/dist/collection/components/split-pane/split-pane.js +3 -2
- package/dist/collection/components/tab/tab.js +2 -2
- package/dist/collection/components/tab-bar/tab-bar.js +2 -2
- package/dist/collection/components/tab-button/tab-button.js +2 -2
- package/dist/collection/components/tabs/tabs.js +1 -1
- package/dist/collection/components/text/text.js +2 -2
- package/dist/collection/components/textarea/textarea.js +3 -3
- package/dist/collection/components/thumbnail/thumbnail.js +2 -2
- package/dist/collection/components/title/title.js +2 -2
- package/dist/collection/components/toast/toast.js +2 -2
- package/dist/collection/components/toggle/toggle.js +3 -3
- package/dist/collection/components/toolbar/toolbar.js +2 -2
- package/dist/collection/utils/css-value-validation.js +25 -0
- package/dist/collection/utils/media.js +1 -0
- package/dist/docs.json +256 -1
- package/dist/esm/ion-app_8.entry.js +7 -7
- package/dist/esm/ion-avatar_3.entry.js +2 -2
- package/dist/esm/ion-col_3.entry.js +8 -6
- package/dist/esm/ion-datetime_3.entry.js +4 -4
- package/dist/esm/ion-gallery.entry.js +488 -0
- package/dist/esm/ion-img.entry.js +2 -2
- package/dist/esm/ion-infinite-scroll_2.entry.js +3 -3
- package/dist/esm/ion-input-otp.entry.js +3 -3
- package/dist/esm/ion-input-password-toggle.entry.js +3 -3
- package/dist/esm/ion-input.entry.js +4 -4
- package/dist/esm/ion-item-option_3.entry.js +4 -4
- package/dist/esm/ion-item_8.entry.js +12 -12
- package/dist/esm/ion-loading.entry.js +2 -2
- package/dist/esm/ion-menu_3.entry.js +6 -6
- package/dist/esm/ion-modal.entry.js +4 -4
- package/dist/esm/ion-nav_2.entry.js +2 -2
- package/dist/esm/ion-picker-column-option.entry.js +2 -2
- package/dist/esm/ion-popover.entry.js +2 -2
- package/dist/esm/ion-progress-bar.entry.js +1 -1
- package/dist/esm/ion-radio_2.entry.js +5 -5
- package/dist/esm/ion-range.entry.js +3 -3
- package/dist/esm/ion-refresher_2.entry.js +3 -3
- package/dist/esm/ion-reorder_2.entry.js +3 -3
- package/dist/esm/ion-ripple-effect.entry.js +1 -1
- package/dist/esm/ion-route_4.entry.js +2 -2
- package/dist/esm/ion-searchbar.entry.js +4 -4
- package/dist/esm/ion-segment-content.entry.js +1 -1
- package/dist/esm/ion-segment-view.entry.js +2 -2
- package/dist/esm/ion-segment_2.entry.js +4 -4
- package/dist/esm/ion-select-modal.entry.js +1 -1
- package/dist/esm/ion-select_3.entry.js +6 -6
- package/dist/esm/ion-spinner.entry.js +1 -1
- package/dist/esm/ion-split-pane.entry.js +3 -2
- package/dist/esm/ion-tab-bar_2.entry.js +4 -4
- package/dist/esm/ion-tab_2.entry.js +3 -3
- package/dist/esm/ion-text.entry.js +2 -2
- package/dist/esm/ion-textarea.entry.js +3 -3
- package/dist/esm/ion-toast.entry.js +2 -2
- package/dist/esm/ion-toggle.entry.js +3 -3
- package/dist/esm/ionic.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/html.html-data.json +74 -0
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/{p-96549175.entry.js → p-00c0bd38.entry.js} +1 -1
- package/dist/ionic/{p-192e7509.entry.js → p-15e3e8f5.entry.js} +1 -1
- package/dist/ionic/{p-5ac21be2.entry.js → p-1709b0aa.entry.js} +1 -1
- package/dist/ionic/{p-2bf931ae.entry.js → p-1c2c1869.entry.js} +1 -1
- package/dist/ionic/{p-3bf01c2c.entry.js → p-1c4de46b.entry.js} +1 -1
- package/dist/ionic/p-1e1c8d61.entry.js +4 -0
- package/dist/ionic/p-2aa7567e.entry.js +4 -0
- package/dist/ionic/{p-bc5713f7.entry.js → p-2ad79c23.entry.js} +1 -1
- package/dist/ionic/{p-5a3fc28e.entry.js → p-2f0073af.entry.js} +1 -1
- package/dist/ionic/{p-833910ae.entry.js → p-35b144f5.entry.js} +1 -1
- package/dist/ionic/{p-59b4f8d0.entry.js → p-3f79f594.entry.js} +1 -1
- package/dist/ionic/p-4079cee3.entry.js +4 -0
- package/dist/ionic/{p-f061fcb7.entry.js → p-48026d15.entry.js} +1 -1
- package/dist/ionic/{p-4091ad21.entry.js → p-50b61fab.entry.js} +1 -1
- package/dist/ionic/{p-8516eb69.entry.js → p-50cd2d57.entry.js} +1 -1
- package/dist/ionic/{p-50d90690.entry.js → p-5274f999.entry.js} +1 -1
- package/dist/ionic/{p-3093958a.entry.js → p-586d4270.entry.js} +1 -1
- package/dist/ionic/{p-6991ffa2.entry.js → p-7054a1b9.entry.js} +1 -1
- package/dist/ionic/{p-b8b20b7e.entry.js → p-71b6014c.entry.js} +1 -1
- package/dist/ionic/{p-9b9b1450.entry.js → p-72491468.entry.js} +1 -1
- package/dist/ionic/{p-c2894f9e.entry.js → p-76307d10.entry.js} +1 -1
- package/dist/ionic/{p-f740c359.entry.js → p-7d5057c4.entry.js} +1 -1
- package/dist/ionic/{p-091a95ea.entry.js → p-83c693c4.entry.js} +1 -1
- package/dist/ionic/{p-2aa44c65.entry.js → p-8537b2fb.entry.js} +1 -1
- package/dist/ionic/{p-02ecc684.entry.js → p-90e653e3.entry.js} +1 -1
- package/dist/ionic/p-96001281.entry.js +4 -0
- package/dist/ionic/{p-98c34fd7.entry.js → p-9d789053.entry.js} +1 -1
- package/dist/ionic/{p-1faf270d.entry.js → p-a9fb086b.entry.js} +1 -1
- package/dist/ionic/{p-e7f216ae.entry.js → p-ae667493.entry.js} +1 -1
- package/dist/ionic/{p-edb0b0c8.entry.js → p-b2fe6c1c.entry.js} +1 -1
- package/dist/ionic/{p-2effd05d.entry.js → p-b3c9f19c.entry.js} +1 -1
- package/dist/ionic/{p-6c8c37c2.entry.js → p-b653f4c2.entry.js} +1 -1
- package/dist/ionic/{p-4e46439d.entry.js → p-bd71a4a7.entry.js} +1 -1
- package/dist/ionic/p-bf972309.entry.js +4 -0
- package/dist/ionic/{p-8180abe5.entry.js → p-c10fa162.entry.js} +1 -1
- package/dist/ionic/{p-d954cd19.entry.js → p-d4ed5710.entry.js} +1 -1
- package/dist/ionic/{p-228b6a9c.entry.js → p-d6299c37.entry.js} +1 -1
- package/dist/ionic/{p-4610e447.entry.js → p-e18d3fdb.entry.js} +1 -1
- package/dist/ionic/{p-4c864eb2.entry.js → p-fad05840.entry.js} +1 -1
- package/dist/types/components/gallery/gallery-constants.d.ts +9 -0
- package/dist/types/components/gallery/gallery-interface.d.ts +10 -0
- package/dist/types/components/gallery/gallery.d.ts +171 -0
- package/dist/types/components/gallery/test/utils.d.ts +2 -0
- package/dist/types/components.d.ts +75 -0
- package/dist/types/utils/css-value-validation.d.ts +12 -0
- package/hydrate/index.js +628 -126
- package/hydrate/index.mjs +628 -126
- package/package.json +1 -1
- package/components/p-CnOTQxHB.js +0 -4
- package/components/p-XFUFdPrc.js +0 -4
- package/components/p-tYh73xQe.js +0 -4
- package/dist/ionic/p-308beb71.entry.js +0 -4
- package/dist/ionic/p-64341e32.entry.js +0 -4
- package/dist/ionic/p-76d0e7ef.entry.js +0 -4
- package/dist/ionic/p-ae4ea663.entry.js +0 -4
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { r as registerInstance, f as printIonWarning, h, d as Host, g as getElement } from './index-Omi_TcwW.js';
|
|
5
|
+
import { r as raf } from './helpers-Do7zwvM1.js';
|
|
6
|
+
import { c as getIonTheme } from './ionic-global-CAZb-5i-.js';
|
|
7
|
+
import './focus-visible-vXpMhGrs.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Helpers for validating user-supplied CSS values using regular expressions, without
|
|
11
|
+
* relying on browser CSS APIs.
|
|
12
|
+
*/
|
|
13
|
+
// Matches `<length>` (`<number>` + unit identifier) or `<percentage>` (`<number>%`).
|
|
14
|
+
const LENGTH_PERCENTAGE_PATTERN = /^[-+]?(?:\d+\.?\d*|\.\d+)(?:%|[a-z]+)$/i;
|
|
15
|
+
// Matches simple `calc` / `min` / `max` / `clamp(...)` functions.
|
|
16
|
+
const MATH_FUNCTION_PATTERN = /^(calc|min|max|clamp)\s*\(.+\)$/i;
|
|
17
|
+
/**
|
|
18
|
+
* Returns whether `value` matches the [length-percentage](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/length-percentage)
|
|
19
|
+
* syntax. Accepts `<length>` (`<number>` + unit identifier) or `<percentage>` (`<number>%`).
|
|
20
|
+
* Also supports simple `calc` / `min` / `max` / `clamp(...)` functions.
|
|
21
|
+
*
|
|
22
|
+
* @param value String value to validate.
|
|
23
|
+
*/
|
|
24
|
+
function isValidLengthPercentage(value) {
|
|
25
|
+
const v = value.trim();
|
|
26
|
+
if (!v) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return MATH_FUNCTION_PATTERN.test(v) || LENGTH_PERCENTAGE_PATTERN.test(v);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const DEFAULT_COLUMNS = {
|
|
33
|
+
xs: 2,
|
|
34
|
+
sm: 3,
|
|
35
|
+
md: 4,
|
|
36
|
+
lg: 6,
|
|
37
|
+
xl: 8,
|
|
38
|
+
xxl: 10,
|
|
39
|
+
};
|
|
40
|
+
const DEFAULT_GAP = '16px';
|
|
41
|
+
|
|
42
|
+
const galleryCss = () => `:host{display:grid;grid-template-columns:repeat(var(--internal-gallery-columns, 2), minmax(0, 1fr))}:host(.gallery-layout-uniform){gap:var(--internal-gallery-gap, 16px)}:host(.gallery-layout-uniform) ::slotted(*){aspect-ratio:1/1}:host(.gallery-layout-masonry){-ms-flex-align:start;align-items:start;-webkit-column-gap:var(--internal-gallery-gap, 16px);-moz-column-gap:var(--internal-gallery-gap, 16px);column-gap:var(--internal-gallery-gap, 16px);row-gap:0;grid-auto-rows:2px}:host(.gallery-layout-masonry) ::slotted(*){display:block;min-height:unset;margin-bottom:var(--internal-gallery-gap, 16px)}::slotted(*){margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;width:100%}::slotted(img){display:block;-o-object-fit:cover;object-fit:cover;-o-object-position:center;object-position:center}`;
|
|
43
|
+
|
|
44
|
+
// TODO(FW-7285): Replace with global breakpoints
|
|
45
|
+
const BREAKPOINTS = {
|
|
46
|
+
xs: 0,
|
|
47
|
+
sm: 576,
|
|
48
|
+
md: 768,
|
|
49
|
+
lg: 992,
|
|
50
|
+
xl: 1200,
|
|
51
|
+
xxl: 1400,
|
|
52
|
+
};
|
|
53
|
+
const BREAKPOINT_ORDER = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'];
|
|
54
|
+
const Gallery = class {
|
|
55
|
+
constructor(hostRef) {
|
|
56
|
+
registerInstance(this, hostRef);
|
|
57
|
+
// Keep track of whether we've warned about invalid columns, invalid gap,
|
|
58
|
+
// and unused order properties to avoid duplicate warnings on screen resize.
|
|
59
|
+
this.hasWarnedInvalidColumns = false;
|
|
60
|
+
this.hasWarnedInvalidGap = false;
|
|
61
|
+
this.hasWarnedUnusedOrder = false;
|
|
62
|
+
/**
|
|
63
|
+
* The visual layout of the gallery. When `uniform`, rows take up the height
|
|
64
|
+
* of the tallest item and are spaced evenly across the gallery. Additionally,
|
|
65
|
+
* items will have an aspect ratio of 1/1, forcing them to be square unless a
|
|
66
|
+
* height is explicitly set. When `masonry`, items will be positioned under each
|
|
67
|
+
* other with only the specified gap between them.
|
|
68
|
+
*/
|
|
69
|
+
this.layout = 'uniform';
|
|
70
|
+
/**
|
|
71
|
+
* The number of columns to display. Can be set as a number or an object of
|
|
72
|
+
* breakpoint values (e.g. `{ xs: 2, sm: 3, md: 4 }`).
|
|
73
|
+
*/
|
|
74
|
+
this.columns = DEFAULT_COLUMNS;
|
|
75
|
+
/**
|
|
76
|
+
* The space between gallery items. Accepts valid CSS [length-percentage](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/length-percentage)
|
|
77
|
+
* values like `16px`, `1rem`, `20%`, math functions like `calc(10px + 20%)`,
|
|
78
|
+
* or numbers (treated as pixel values). Can also be set as a breakpoint map
|
|
79
|
+
* (e.g. `{ xs: '8px', sm: '1rem', md: '24px' }`). Does not accept
|
|
80
|
+
* space-separated values or CSS keyword values like `inherit`, `auto`, etc.
|
|
81
|
+
*/
|
|
82
|
+
this.gap = DEFAULT_GAP;
|
|
83
|
+
/**
|
|
84
|
+
* Listen for the slotchange event on the slot.
|
|
85
|
+
* When the layout is `masonry`, this listener is used to schedule a resize
|
|
86
|
+
* of the masonry grid when the slot changes. This is useful for when items
|
|
87
|
+
* are added or removed from the gallery.
|
|
88
|
+
*/
|
|
89
|
+
this.onSlotChange = () => {
|
|
90
|
+
this.scheduleMasonryResize();
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Measure the host and children, then compute masonry placement.
|
|
94
|
+
*/
|
|
95
|
+
this.resizeMasonryGrid = () => {
|
|
96
|
+
this.masonryRaf = undefined;
|
|
97
|
+
if (this.layout !== 'masonry') {
|
|
98
|
+
this.clearMasonryStyles();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const width = this.el.getBoundingClientRect().width;
|
|
102
|
+
const columns = this.getColumnsForWidth(width);
|
|
103
|
+
// Skip masonry placement when width/columns does not resolve
|
|
104
|
+
// to a valid breakpoint column count.
|
|
105
|
+
if (columns === undefined) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const styles = getComputedStyle(this.el);
|
|
109
|
+
const rowHeight = parseFloat(styles.getPropertyValue('grid-auto-rows')) || 0;
|
|
110
|
+
const rowGap = parseFloat(styles.getPropertyValue('row-gap')) || parseFloat(styles.getPropertyValue('gap')) || 0;
|
|
111
|
+
const items = this.getItems();
|
|
112
|
+
this.layoutMasonry(items, rowHeight, rowGap, columns);
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
propertiesChanged() {
|
|
116
|
+
this.updateResponsiveStyles(true);
|
|
117
|
+
this.scheduleMasonryResize();
|
|
118
|
+
// Wait until the next animation frame to warn about unused order
|
|
119
|
+
// to avoid erroneous warnings when the layout and order are updated
|
|
120
|
+
// in the same frame.
|
|
121
|
+
raf(() => {
|
|
122
|
+
this.warnUnusedOrder();
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
componentDidLoad() {
|
|
126
|
+
this.updateResponsiveStyles(true);
|
|
127
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
128
|
+
this.updateResponsiveStyles();
|
|
129
|
+
this.scheduleMasonryResize();
|
|
130
|
+
});
|
|
131
|
+
this.resizeObserver.observe(this.el);
|
|
132
|
+
this.scheduleMasonryResize();
|
|
133
|
+
this.warnUnusedOrder();
|
|
134
|
+
}
|
|
135
|
+
disconnectedCallback() {
|
|
136
|
+
var _a;
|
|
137
|
+
if (this.masonryRaf !== undefined) {
|
|
138
|
+
cancelAnimationFrame(this.masonryRaf);
|
|
139
|
+
this.masonryRaf = undefined;
|
|
140
|
+
}
|
|
141
|
+
(_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
142
|
+
this.resizeObserver = undefined;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Listen for the load event on child elements.
|
|
146
|
+
* When the layout is `masonry`, this listener is used to schedule a resize
|
|
147
|
+
* of the masonry grid when the child elements load. This is useful for when
|
|
148
|
+
* images take time to load.
|
|
149
|
+
*/
|
|
150
|
+
onChildLoad(ev) {
|
|
151
|
+
if (this.layout !== 'masonry') {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const target = ev.target;
|
|
155
|
+
if (target !== null && this.el.contains(target)) {
|
|
156
|
+
this.scheduleMasonryResize();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Batch masonry measurements to a single animation frame.
|
|
161
|
+
* This avoids repeated sync layouts during rapid resize/load/slot changes.
|
|
162
|
+
*/
|
|
163
|
+
scheduleMasonryResize() {
|
|
164
|
+
if (this.layout !== 'masonry') {
|
|
165
|
+
this.clearMasonryStyles();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (this.masonryRaf !== undefined) {
|
|
169
|
+
cancelAnimationFrame(this.masonryRaf);
|
|
170
|
+
}
|
|
171
|
+
this.masonryRaf = requestAnimationFrame(this.resizeMasonryGrid);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Normalize a single column value (`columns` as a number, string, or one entry from
|
|
175
|
+
* a `columns` breakpoint map) to a positive integer. Returns `undefined` when
|
|
176
|
+
* the input cannot be interpreted as a finite number.
|
|
177
|
+
*/
|
|
178
|
+
sanitizeColumns(columns) {
|
|
179
|
+
if (columns === undefined) {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
const numericColumns = typeof columns === 'number' ? columns : Number(columns);
|
|
183
|
+
if (!Number.isFinite(numericColumns) || !Number.isInteger(numericColumns) || numericColumns <= 0) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
return numericColumns;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Normalize a single gap value (`gap` as a number, string, or one entry from
|
|
190
|
+
* a `gap` breakpoint map) to a CSS length string. Returns `undefined` when
|
|
191
|
+
* the input cannot be interpreted as a valid CSS length.
|
|
192
|
+
*/
|
|
193
|
+
sanitizeGap(gap) {
|
|
194
|
+
if (gap === undefined) {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
const normalizedGap = typeof gap === 'string' ? gap.trim() : gap;
|
|
198
|
+
if (normalizedGap === '' || typeof normalizedGap === 'object') {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
const numericGap = Number(normalizedGap);
|
|
202
|
+
if (Number.isFinite(numericGap)) {
|
|
203
|
+
return numericGap < 0 ? undefined : `${numericGap}px`;
|
|
204
|
+
}
|
|
205
|
+
if (typeof normalizedGap !== 'string') {
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
const isValidCssLength = isValidLengthPercentage(normalizedGap);
|
|
209
|
+
return isValidCssLength ? normalizedGap : undefined;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Check if the value is a breakpoint map object.
|
|
213
|
+
*/
|
|
214
|
+
isBreakpointMap(value) {
|
|
215
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Check if the breakpoint map has any invalid values for the provided sanitizer.
|
|
219
|
+
*/
|
|
220
|
+
hasInvalidBreakpointMap(breakpointMap, sanitizeValue) {
|
|
221
|
+
for (const breakpoint of BREAKPOINT_ORDER) {
|
|
222
|
+
const value = breakpointMap[breakpoint];
|
|
223
|
+
if (value !== undefined && sanitizeValue(value) === undefined) {
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Resolve a responsive value from a breakpoint map.
|
|
231
|
+
* Uses a breakpoint-specific default when custom values are missing/invalid.
|
|
232
|
+
*/
|
|
233
|
+
resolveFromBreakpoints(width, breakpointMap, sanitizeProvided, getSanitizedDefault) {
|
|
234
|
+
let resolvedValue;
|
|
235
|
+
for (const bp of BREAKPOINT_ORDER) {
|
|
236
|
+
const providedValue = breakpointMap[bp];
|
|
237
|
+
const sanitizedProvided = sanitizeProvided(providedValue);
|
|
238
|
+
const sanitizedDefault = getSanitizedDefault(bp);
|
|
239
|
+
const resolved = providedValue === undefined || sanitizedProvided === undefined ? sanitizedDefault : sanitizedProvided;
|
|
240
|
+
if (resolved !== undefined && width >= BREAKPOINTS[bp]) {
|
|
241
|
+
resolvedValue = resolved;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return resolvedValue;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Get the columns from a responsive breakpoint map.
|
|
248
|
+
* Returns the columns for the last matching breakpoint.
|
|
249
|
+
*/
|
|
250
|
+
getColumnsFromBreakpointMap(width, breakpointMap) {
|
|
251
|
+
return this.resolveFromBreakpoints(width, breakpointMap, (value) => this.sanitizeColumns(value), (bp) => this.sanitizeColumns(DEFAULT_COLUMNS[bp]));
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Get the gap from a responsive breakpoint map.
|
|
255
|
+
* Returns the gap for the last matching breakpoint.
|
|
256
|
+
*/
|
|
257
|
+
getGapFromBreakpointMap(width, breakpointMap) {
|
|
258
|
+
return this.resolveFromBreakpoints(width, breakpointMap, (value) => this.sanitizeGap(value), () => this.sanitizeGap(DEFAULT_GAP));
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Warn about an invalid columns value when it is set to a non-positive
|
|
262
|
+
* integer or a breakpoint map object with invalid values.
|
|
263
|
+
*/
|
|
264
|
+
warnInvalidColumns(columns) {
|
|
265
|
+
if (this.hasWarnedInvalidColumns) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
printIonWarning(`[ion-gallery] - Invalid "columns" value (${JSON.stringify(columns)}). Expected a positive integer or breakpoint map object (e.g. { xs: 2, md: 4 }). Falling back to default responsive columns.`, this.el);
|
|
269
|
+
this.hasWarnedInvalidColumns = true;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Warn about an invalid gap value when it is set to a negative number
|
|
273
|
+
* or a breakpoint map object with invalid values.
|
|
274
|
+
*/
|
|
275
|
+
warnInvalidGap(gap) {
|
|
276
|
+
if (this.hasWarnedInvalidGap) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
printIonWarning(`[ion-gallery] - Invalid "gap" value (${JSON.stringify(gap)}). Expected a non-negative number, CSS length string, or breakpoint map object (e.g. { xs: 8, md: "1rem" }).`, this.el);
|
|
280
|
+
this.hasWarnedInvalidGap = true;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Warn when `order` is explicitly set while layout is `uniform`.
|
|
284
|
+
*/
|
|
285
|
+
warnUnusedOrder() {
|
|
286
|
+
const { layout } = this;
|
|
287
|
+
const order = this.order == null ? undefined : this.order;
|
|
288
|
+
if (this.hasWarnedUnusedOrder || layout !== 'uniform' || order === undefined) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
printIonWarning(`[ion-gallery] - "order" has no effect when "layout" is "uniform". Set "layout" to "masonry" for "order" to apply.`, this.el);
|
|
292
|
+
this.hasWarnedUnusedOrder = true;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Resolve the active columns value for the current width. Falls back to
|
|
296
|
+
* the default responsive columns when the provided prop is invalid.
|
|
297
|
+
*/
|
|
298
|
+
getColumnsForWidth(width) {
|
|
299
|
+
const { columns } = this;
|
|
300
|
+
const isBreakpointColumns = this.isBreakpointMap(columns);
|
|
301
|
+
const hasInvalidBreakpointColumns = isBreakpointColumns && this.hasInvalidBreakpointMap(columns, (value) => this.sanitizeColumns(value));
|
|
302
|
+
const sanitizedColumns = isBreakpointColumns
|
|
303
|
+
? this.getColumnsFromBreakpointMap(width, columns)
|
|
304
|
+
: this.sanitizeColumns(columns);
|
|
305
|
+
if (hasInvalidBreakpointColumns || (!isBreakpointColumns && sanitizedColumns === undefined)) {
|
|
306
|
+
this.warnInvalidColumns(columns);
|
|
307
|
+
}
|
|
308
|
+
if (sanitizedColumns !== undefined) {
|
|
309
|
+
return sanitizedColumns;
|
|
310
|
+
}
|
|
311
|
+
return this.getColumnsFromBreakpointMap(width, DEFAULT_COLUMNS);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Resolve the active gap value for the current width.
|
|
315
|
+
*/
|
|
316
|
+
getGapForWidth(width) {
|
|
317
|
+
const { gap } = this;
|
|
318
|
+
const providedGap = gap !== null && gap !== void 0 ? gap : DEFAULT_GAP;
|
|
319
|
+
const isBreakpointGap = this.isBreakpointMap(providedGap);
|
|
320
|
+
const hasInvalidBreakpointGap = isBreakpointGap && this.hasInvalidBreakpointMap(providedGap, (value) => this.sanitizeGap(value));
|
|
321
|
+
const sanitizedGap = isBreakpointGap
|
|
322
|
+
? this.getGapFromBreakpointMap(width, providedGap)
|
|
323
|
+
: this.sanitizeGap(providedGap);
|
|
324
|
+
if (hasInvalidBreakpointGap || (!isBreakpointGap && sanitizedGap === undefined)) {
|
|
325
|
+
this.warnInvalidGap(providedGap);
|
|
326
|
+
}
|
|
327
|
+
if (sanitizedGap !== undefined) {
|
|
328
|
+
return sanitizedGap;
|
|
329
|
+
}
|
|
330
|
+
return this.sanitizeGap(DEFAULT_GAP);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Update the responsive styles for the gallery. This is used to update
|
|
334
|
+
* the columns and gap when the component width changes.
|
|
335
|
+
*/
|
|
336
|
+
updateResponsiveStyles(force = false) {
|
|
337
|
+
const width = this.el.getBoundingClientRect().width;
|
|
338
|
+
// Only update the columns if the component width has changed by more than
|
|
339
|
+
// 1px or if the force flag is true. This prevents unnecessary re-renders
|
|
340
|
+
// when the component width has not changed.
|
|
341
|
+
if (!width || (!force && this.lastWidth !== undefined && Math.abs(this.lastWidth - width) < 1)) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
this.lastWidth = width;
|
|
345
|
+
const columns = this.getColumnsForWidth(width);
|
|
346
|
+
this.el.style.setProperty('--internal-gallery-columns', `${columns}`);
|
|
347
|
+
const gap = this.getGapForWidth(width);
|
|
348
|
+
this.el.style.setProperty('--internal-gallery-gap', `${gap}`);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Return all directly slotted HTMLElement children of the gallery.
|
|
352
|
+
*/
|
|
353
|
+
getItems() {
|
|
354
|
+
return Array.from(this.el.children).filter((child) => child instanceof HTMLElement);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Clear the item styles for the given item element.
|
|
358
|
+
* This is used to switch between uniform and masonry layouts.
|
|
359
|
+
*/
|
|
360
|
+
clearItemStyles(itemEl) {
|
|
361
|
+
itemEl.style.gridRowStart = '';
|
|
362
|
+
itemEl.style.gridRowEnd = '';
|
|
363
|
+
itemEl.style.gridColumn = '';
|
|
364
|
+
itemEl.style.marginBottom = '';
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Clear placement styles for all items when leaving masonry mode.
|
|
368
|
+
*/
|
|
369
|
+
clearMasonryStyles() {
|
|
370
|
+
this.getItems().forEach((itemEl) => this.clearItemStyles(itemEl));
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Convert a rendered item height to the number of grid rows it should span.
|
|
374
|
+
* Returns undefined for images that are not fully loaded yet.
|
|
375
|
+
*/
|
|
376
|
+
calculateRowSpan(itemEl, rowHeight, rowGap) {
|
|
377
|
+
if (itemEl instanceof HTMLImageElement && (!itemEl.complete || itemEl.naturalHeight === 0)) {
|
|
378
|
+
return undefined;
|
|
379
|
+
}
|
|
380
|
+
const height = itemEl.getBoundingClientRect().height;
|
|
381
|
+
const itemStyles = getComputedStyle(itemEl);
|
|
382
|
+
const marginBottom = parseFloat(itemStyles.getPropertyValue('margin-bottom')) || 0;
|
|
383
|
+
const denominator = rowHeight + rowGap;
|
|
384
|
+
if (!denominator || !Number.isFinite(denominator)) {
|
|
385
|
+
return 1;
|
|
386
|
+
}
|
|
387
|
+
return Math.ceil((height + marginBottom + rowGap) / denominator) || 1;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Get the index of the column to position the item in.
|
|
391
|
+
* When the order is `best-fit`, the column with the shortest height is
|
|
392
|
+
* returned. Otherwise, items are placed in the column that matches their
|
|
393
|
+
* natural DOM order.
|
|
394
|
+
*/
|
|
395
|
+
getColumnIndex(index, columnHeights, columns) {
|
|
396
|
+
const order = this.getOrder();
|
|
397
|
+
if (order === 'best-fit') {
|
|
398
|
+
let columnIndex = 0;
|
|
399
|
+
for (let i = 1; i < columns; i++) {
|
|
400
|
+
if (columnHeights[i] < columnHeights[columnIndex]) {
|
|
401
|
+
columnIndex = i;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
return columnIndex;
|
|
405
|
+
}
|
|
406
|
+
return index % columns;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Apply masonry placement by assigning each item a column and row span.
|
|
410
|
+
*/
|
|
411
|
+
layoutMasonry(items, rowHeight, rowGap, columns) {
|
|
412
|
+
const columnHeights = new Array(columns).fill(0);
|
|
413
|
+
const lastItemsByColumn = new Array(columns).fill(undefined);
|
|
414
|
+
items.forEach((itemEl, i) => {
|
|
415
|
+
itemEl.style.marginBottom = '';
|
|
416
|
+
const span = this.calculateRowSpan(itemEl, rowHeight, rowGap);
|
|
417
|
+
if (span === undefined) {
|
|
418
|
+
this.clearItemStyles(itemEl);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
const columnIndex = this.getColumnIndex(i, columnHeights, columns);
|
|
422
|
+
const start = columnHeights[columnIndex] + 1;
|
|
423
|
+
itemEl.style.gridColumn = `${columnIndex + 1}`;
|
|
424
|
+
itemEl.style.gridRowStart = `${start}`;
|
|
425
|
+
itemEl.style.gridRowEnd = `span ${span}`;
|
|
426
|
+
columnHeights[columnIndex] = start + span - 1;
|
|
427
|
+
lastItemsByColumn[columnIndex] = itemEl;
|
|
428
|
+
});
|
|
429
|
+
// Remove trailing space from the final item in each column while preserving
|
|
430
|
+
// spacing between all non-final items.
|
|
431
|
+
lastItemsByColumn.forEach((itemEl) => {
|
|
432
|
+
if (itemEl === undefined) {
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
itemEl.style.marginBottom = '0px';
|
|
436
|
+
const spanWithoutTrailingGap = this.calculateRowSpan(itemEl, rowHeight, rowGap);
|
|
437
|
+
if (spanWithoutTrailingGap === undefined) {
|
|
438
|
+
this.clearItemStyles(itemEl);
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
itemEl.style.gridRowEnd = `span ${spanWithoutTrailingGap}`;
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Resolved order for layout and CSS. Order should be `undefined` for
|
|
446
|
+
* the uniform layout. When order is not set, it should be `"sequential"`
|
|
447
|
+
* for the masonry layout.
|
|
448
|
+
*/
|
|
449
|
+
getOrder() {
|
|
450
|
+
const { layout } = this;
|
|
451
|
+
const order = this.order == null ? undefined : this.order;
|
|
452
|
+
if (layout === 'uniform') {
|
|
453
|
+
return undefined;
|
|
454
|
+
}
|
|
455
|
+
if (layout === 'masonry' && order === undefined) {
|
|
456
|
+
return 'sequential';
|
|
457
|
+
}
|
|
458
|
+
return order;
|
|
459
|
+
}
|
|
460
|
+
render() {
|
|
461
|
+
const { layout } = this;
|
|
462
|
+
const order = this.getOrder();
|
|
463
|
+
const theme = getIonTheme(this);
|
|
464
|
+
return (h(Host, { key: '8a8266626f1ba8beb7e382c89ae7905372fe23a9', class: {
|
|
465
|
+
[theme]: true,
|
|
466
|
+
[`gallery-layout-${layout}`]: true,
|
|
467
|
+
[`gallery-order-${order}`]: layout === 'masonry' && order !== undefined,
|
|
468
|
+
} }, h("slot", { key: '7758e89bda53a91d593b9ece0cbe60a4bce0a0fa', onSlotchange: this.onSlotChange })));
|
|
469
|
+
}
|
|
470
|
+
get el() { return getElement(this); }
|
|
471
|
+
static get watchers() { return {
|
|
472
|
+
"columns": [{
|
|
473
|
+
"propertiesChanged": 0
|
|
474
|
+
}],
|
|
475
|
+
"gap": [{
|
|
476
|
+
"propertiesChanged": 0
|
|
477
|
+
}],
|
|
478
|
+
"layout": [{
|
|
479
|
+
"propertiesChanged": 0
|
|
480
|
+
}],
|
|
481
|
+
"order": [{
|
|
482
|
+
"propertiesChanged": 0
|
|
483
|
+
}]
|
|
484
|
+
}; }
|
|
485
|
+
};
|
|
486
|
+
Gallery.style = galleryCss();
|
|
487
|
+
|
|
488
|
+
export { Gallery as ion_gallery };
|
|
@@ -82,9 +82,9 @@ const Img = class {
|
|
|
82
82
|
const { loadSrc, alt, onLoad, loadError, inheritedAttributes } = this;
|
|
83
83
|
const { draggable } = inheritedAttributes;
|
|
84
84
|
const theme = getIonTheme(this);
|
|
85
|
-
return (h(Host, { key: '
|
|
85
|
+
return (h(Host, { key: '91de170493b31d6260e975b440beceb6906b6d5a', class: {
|
|
86
86
|
[theme]: true,
|
|
87
|
-
} }, h("img", { key: '
|
|
87
|
+
} }, h("img", { key: 'ac1f41afbece34a3e38e656733f3e55cce385b4c', decoding: "async", src: loadSrc, alt: alt, onLoad: onLoad, onError: loadError, part: "image", draggable: isDraggable(draggable) })));
|
|
88
88
|
}
|
|
89
89
|
get el() { return getElement(this); }
|
|
90
90
|
static get watchers() { return {
|
|
@@ -269,7 +269,7 @@ const InfiniteScroll = class {
|
|
|
269
269
|
render() {
|
|
270
270
|
const theme = getIonTheme(this);
|
|
271
271
|
const disabled = this.disabled;
|
|
272
|
-
return (h(Host, { key: '
|
|
272
|
+
return (h(Host, { key: '02beca21d668e4e605532ad5ca5a67a08c71eebb', class: {
|
|
273
273
|
[theme]: true,
|
|
274
274
|
'infinite-scroll-loading': this.isLoading,
|
|
275
275
|
'infinite-scroll-enabled': !disabled,
|
|
@@ -313,11 +313,11 @@ const InfiniteScrollContent = class {
|
|
|
313
313
|
}
|
|
314
314
|
render() {
|
|
315
315
|
const theme = getIonTheme(this);
|
|
316
|
-
return (h(Host, { key: '
|
|
316
|
+
return (h(Host, { key: 'b51954f829eeafd5ec304b3e66e330776485ffc8', class: {
|
|
317
317
|
[theme]: true,
|
|
318
318
|
// Used internally for styling
|
|
319
319
|
[`infinite-scroll-content-${theme}`]: true,
|
|
320
|
-
} }, h("div", { key: '
|
|
320
|
+
} }, h("div", { key: '047da7f15fe38deed592dd66d1c97e12da4545bb', class: "infinite-loading" }, this.loadingSpinner && (h("div", { key: '1c05820f091052b8ee9e9ca20054495a676c21aa', class: "infinite-loading-spinner" }, h("ion-spinner", { key: 'ff801e3486f3c1a4605d2a2de9b47bd7bd536698', name: this.loadingSpinner }))), this.loadingText !== undefined && this.renderLoadingText())));
|
|
321
321
|
}
|
|
322
322
|
};
|
|
323
323
|
InfiniteScrollContent.style = {
|
|
@@ -690,7 +690,7 @@ const InputOTP = class {
|
|
|
690
690
|
const tabbableIndex = this.getTabbableIndex();
|
|
691
691
|
const pattern = this.getPattern();
|
|
692
692
|
const hasDescription = ((_b = (_a = el.querySelector('.input-otp-description')) === null || _a === void 0 ? void 0 : _a.textContent) === null || _b === void 0 ? void 0 : _b.trim()) !== '';
|
|
693
|
-
return (h(Host, { key: '
|
|
693
|
+
return (h(Host, { key: '7a5c5dbb7e1880bd94d4b00e579af941366b1cb2', class: createColorClasses(color, {
|
|
694
694
|
[mode]: true,
|
|
695
695
|
'has-focus': hasFocus,
|
|
696
696
|
[`input-otp-size-${size}`]: true,
|
|
@@ -698,10 +698,10 @@ const InputOTP = class {
|
|
|
698
698
|
[`input-otp-fill-${fill}`]: true,
|
|
699
699
|
'input-otp-disabled': disabled,
|
|
700
700
|
'input-otp-readonly': readonly,
|
|
701
|
-
}) }, h("div", Object.assign({ key: '
|
|
701
|
+
}) }, h("div", Object.assign({ key: 'a4427602ea1894d53e4d0f502dbb972c93a86bff', role: "group", "aria-label": "One-time password input", class: "input-otp-group", part: "group" }, inheritedAttributes), Array.from({ length }).map((_, index) => (h(Fragment, null, h("div", { class: "native-wrapper", part: "container" }, h("input", { class: "native-input", part: "native", id: `${inputId}-${index}`, "aria-label": `Input ${index + 1} of ${length}`, type: "text", autoCapitalize: autocapitalize, inputmode: inputmode, pattern: pattern, disabled: disabled, readOnly: readonly, tabIndex: index === tabbableIndex ? 0 : -1, value: inputValues[index] || '', autocomplete: "one-time-code", ref: (el) => (inputRefs[index] = el), onInput: this.onInput(index), onBlur: this.onBlur, onFocus: this.onFocus(index), onKeyDown: this.onKeyDown(index), onPaste: this.onPaste })), this.showSeparator(index) && h("div", { class: "input-otp-separator", part: "separator" }))))), h("div", { key: '7ee9d8dfd2e52875f1bfe3e3dea0494c18c12f4a', class: {
|
|
702
702
|
'input-otp-description': true,
|
|
703
703
|
'input-otp-description-hidden': !hasDescription,
|
|
704
|
-
}, part: "description" }, h("slot", { key: '
|
|
704
|
+
}, part: "description" }, h("slot", { key: '163c374e7ae5dbdb1dc12483161e5aca919a50d5' }))));
|
|
705
705
|
}
|
|
706
706
|
static get formAssociated() { return true; }
|
|
707
707
|
get el() { return getElement(this); }
|
|
@@ -99,16 +99,16 @@ const InputPasswordToggle = class {
|
|
|
99
99
|
const { color, inputPasswordHideIcon, inputPasswordShowIcon, type } = this;
|
|
100
100
|
const mode = getIonMode(this);
|
|
101
101
|
const isPasswordVisible = type === 'text';
|
|
102
|
-
return (h(Host, { key: '
|
|
102
|
+
return (h(Host, { key: 'c7f0805958b284005806a0cb3ed0b5cba42cecd1', class: createColorClasses(color, {
|
|
103
103
|
[mode]: true,
|
|
104
|
-
}) }, h("ion-button", { key: '
|
|
104
|
+
}) }, h("ion-button", { key: 'dee2bdeb169d1fa4943c9a8b0164b8fbb4cdfe06', mode: mode, color: color, fill: "clear", shape: "round", "aria-label": isPasswordVisible ? 'Hide password' : 'Show password', "aria-pressed": isPasswordVisible ? 'true' : 'false', type: "button", onPointerDown: (ev) => {
|
|
105
105
|
/**
|
|
106
106
|
* This prevents mobile browsers from
|
|
107
107
|
* blurring the input when the password toggle
|
|
108
108
|
* button is activated.
|
|
109
109
|
*/
|
|
110
110
|
ev.preventDefault();
|
|
111
|
-
}, onClick: this.togglePasswordVisibility }, h("ion-icon", { key: '
|
|
111
|
+
}, onClick: this.togglePasswordVisibility }, h("ion-icon", { key: 'be752db7186a7cd6fc033c7002fcb1683d93c162', slot: "icon-only", "aria-hidden": "true", icon: isPasswordVisible ? inputPasswordHideIcon : inputPasswordShowIcon }))));
|
|
112
112
|
}
|
|
113
113
|
get el() { return getElement(this); }
|
|
114
114
|
static get watchers() { return {
|
|
@@ -620,7 +620,7 @@ const Input = class {
|
|
|
620
620
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
621
621
|
*/
|
|
622
622
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
623
|
-
return (h(Host, { key: '
|
|
623
|
+
return (h(Host, { key: 'beeeca9939e7e416783425f67d3c9e2be6bbae99', class: createColorClasses(this.color, {
|
|
624
624
|
[theme]: true,
|
|
625
625
|
'has-value': hasValue,
|
|
626
626
|
'has-focus': hasFocus,
|
|
@@ -633,7 +633,7 @@ const Input = class {
|
|
|
633
633
|
'in-item-color': hostContext('ion-item.ion-color', this.el),
|
|
634
634
|
'input-disabled': disabled,
|
|
635
635
|
'input-readonly': readonly,
|
|
636
|
-
}) }, h("label", { key: '
|
|
636
|
+
}) }, h("label", { key: 'f227df52a6ad60344f16261a82c0d0566bb8cd5b', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: 'ae6da554ce21f805361a7704139b776a9344dcb2', class: "native-wrapper", onClick: this.onLabelClick },
|
|
637
637
|
/**
|
|
638
638
|
* For the ionic theme, we render the outline container here
|
|
639
639
|
* instead of higher up, so it can be positioned relative to
|
|
@@ -643,14 +643,14 @@ const Input = class {
|
|
|
643
643
|
* <label> element, ensuring that clicking the label text
|
|
644
644
|
* focuses the input.
|
|
645
645
|
*/
|
|
646
|
-
theme === 'ionic' && h("div", { key: '
|
|
646
|
+
theme === 'ionic' && h("div", { key: '83aa5e7ad97b0c964e31966c1d2b8771d1ecfc53', class: "input-outline" }), h("slot", { key: '1931003f2b0d19508acaaffab58fee644d1f6158', name: "start" }), h("input", Object.assign({ key: '33a06efb4ce0b6e67c12e77f131effb113fba73f', class: "native-input", ref: (input) => (this.nativeInput = input), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, min: this.min, max: this.max, minLength: this.minlength, maxLength: this.maxlength, multiple: this.multiple, name: this.name, pattern: this.pattern, placeholder: this.placeholder || '', readOnly: readonly, required: this.required, spellcheck: this.spellcheck, step: this.step, type: this.type, value: value, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeydown, onCompositionstart: this.onCompositionStart, onCompositionend: this.onCompositionEnd, "aria-describedby": this.getHintTextID(), "aria-invalid": this.isInvalid ? 'true' : undefined, "aria-labelledby": this.getLabelledById() }, this.inheritedAttributes)), clearInput && !readonly && !disabled && (h("button", { key: 'd350f26cf6927ee089373ea8903db2479a0a404c', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
|
|
647
647
|
/**
|
|
648
648
|
* This prevents mobile browsers from
|
|
649
649
|
* blurring the input when the clear
|
|
650
650
|
* button is activated.
|
|
651
651
|
*/
|
|
652
652
|
ev.preventDefault();
|
|
653
|
-
}, onClick: this.clearTextInput }, h("ion-icon", { key: '
|
|
653
|
+
}, onClick: this.clearTextInput }, h("ion-icon", { key: '972a2d94dcf599e63aac1d73e34873a9c3d0bf94', "aria-hidden": "true", icon: inputClearIcon }))), h("slot", { key: 'fac4dcaabb02f647e46276e92e3f341557170aec', name: "end" })), shouldRenderHighlight && h("div", { key: 'a10e519d8d1f0dcd81ffc43b8e4086797476f753', class: "input-highlight" })), this.renderBottomContent()));
|
|
654
654
|
}
|
|
655
655
|
get el() { return getElement(this); }
|
|
656
656
|
static get watchers() { return {
|
|
@@ -68,14 +68,14 @@ const ItemOption = class {
|
|
|
68
68
|
href: this.href,
|
|
69
69
|
target: this.target,
|
|
70
70
|
};
|
|
71
|
-
return (h(Host, { key: '
|
|
71
|
+
return (h(Host, { key: 'bfade0042108ff525077dfbdfd45169ccfd6b920', onClick: this.onClick, class: createColorClasses(this.color, {
|
|
72
72
|
[theme]: true,
|
|
73
73
|
[`item-option-${shape}`]: shape !== undefined,
|
|
74
74
|
[`item-option-${hue}`]: hue !== undefined,
|
|
75
75
|
'item-option-disabled': disabled,
|
|
76
76
|
'item-option-expandable': expandable,
|
|
77
77
|
'ion-activatable': true,
|
|
78
|
-
}) }, h(TagType, Object.assign({ key: '
|
|
78
|
+
}) }, h(TagType, Object.assign({ key: '38466b511f4a20a3728f37dbf6779b852eba531a' }, attrs, { class: "button-native", part: "native", disabled: disabled }), h("span", { key: 'bb8f1b332afa2f575bcc69b340bd8f1faa5ca925', class: "button-inner", part: "inner" }, h("slot", { key: '41d627511e1615283956712e1b9519bae92460f6', name: "top" }), h("div", { key: 'bb949a43a586a8996933ee7528e5491beb647aa5', class: "horizontal-wrapper", part: "container" }, h("slot", { key: 'c0d6a73ef49082bfbdf0f542f7465d044ccb6521', name: "start" }), h("slot", { key: '79c6103e680983b2c1a17f1f11dbc41224cd4016', name: "icon-only" }), h("slot", { key: '6c7f17723544d3f6e8b9689b84ddf6196f1897a5' }), h("slot", { key: 'e15d0e02fde71bad8ff7bab0eded7d49508a926e', name: "end" })), h("slot", { key: 'c509d54d44ce33f5a34597b9d0ec29960bbcff62', name: "bottom" })), theme === 'md' && h("ion-ripple-effect", { key: '412d4dc645c941d0b4356cf982be3d5bc2686f13' }))));
|
|
79
79
|
}
|
|
80
80
|
get el() { return getElement(this); }
|
|
81
81
|
};
|
|
@@ -110,7 +110,7 @@ const ItemOptions = class {
|
|
|
110
110
|
render() {
|
|
111
111
|
const theme = getIonTheme(this);
|
|
112
112
|
const isEnd = isEndSide(this.side);
|
|
113
|
-
return (h(Host, { key: '
|
|
113
|
+
return (h(Host, { key: 'f3bb726a28c571101791d33d946df9017f47e5ec', class: {
|
|
114
114
|
[theme]: true,
|
|
115
115
|
// Used internally for styling
|
|
116
116
|
[`item-options-${theme}`]: true,
|
|
@@ -904,7 +904,7 @@ const ItemSliding = class {
|
|
|
904
904
|
}
|
|
905
905
|
render() {
|
|
906
906
|
const theme = getIonTheme(this);
|
|
907
|
-
return (h(Host, { key: '
|
|
907
|
+
return (h(Host, { key: 'e6890a1b14faaf9121a07912b1c2f46e06148202', class: {
|
|
908
908
|
[theme]: true,
|
|
909
909
|
'item-sliding-active-slide': this.state !== 2 /* SlidingState.Disabled */,
|
|
910
910
|
'item-sliding-active-options-end': (this.state & 8 /* SlidingState.End */) !== 0,
|