Skip to content

Commit

Permalink
Merge dd6d992 into 3d8f526
Browse files Browse the repository at this point in the history
  • Loading branch information
EdwardCoyle committed May 18, 2021
2 parents 3d8f526 + dd6d992 commit 9beee53
Show file tree
Hide file tree
Showing 39 changed files with 1,517 additions and 57 deletions.
26 changes: 26 additions & 0 deletions app/ids-modal/example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<ids-modal id="my-modal">
<ids-layout-grid>
<ids-text font-size="24" type="h2">Active IDS Modal</ids-text>
</ids-layout-grid>
<ids-layout-grid>
<p>This is an active IDS Modal component</p>
</ids-layout-grid>
<ids-layout-grid auto="true">
<ids-layout-grid-cell>
<ids-button id="modal-close-btn" type="secondary">
<span slot="text">OK</span>
</ids-button>
</ids-layout-grid-cell>
</ids-layout-grid>
</ids-modal>

<ids-layout-grid>
<ids-text font-size="12" type="h1">Modal</ids-text>
</ids-layout-grid>
<ids-layout-grid auto="true">
<ids-layout-grid-cell>
<ids-button id="modal-trigger-btn" type="secondary">
<span slot="text">Trigger a Modal</span>
</ids-button>
</ids-layout-grid-cell>
</ids-layout-grid>
28 changes: 28 additions & 0 deletions app/ids-modal/example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Supporting Components
import IdsButton from '../../src/ids-button/ids-button';

document.addEventListener('DOMContentLoaded', () => {
const triggerId = '#modal-trigger-btn';
const triggerBtn = document.querySelector(triggerId);
const modal = document.querySelector('ids-modal');
const modalCloseBtn = modal.querySelector('ids-button');

// Links the Modal to its trigger button (sets up click/focus events)
modal.target = triggerBtn;

// Disable the trigger button when showing the Modal.
modal.addEventListener('beforeshow', () => {
triggerBtn.disabled = true;
return true;
});

// Close the modal when its inner button is clicked.
modalCloseBtn.addEventListener('click', () => {
modal.hide();
});

// After the modal is done hiding, re-enable its trigger button.
modal.addEventListener('hide', () => {
triggerBtn.disabled = false;
});
});
3 changes: 3 additions & 0 deletions app/ids-modal/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{{> ../layouts/head.html }}
{{> example.html }}
{{> ../layouts/footer.html }}
1 change: 1 addition & 0 deletions app/ids-modal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import IdsModal from '../../src/ids-modal/ids-modal';
50 changes: 50 additions & 0 deletions app/ids-modal/nested.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{{> ../layouts/head.html }}

<ids-modal id="parent-modal">
<ids-layout-grid>
<ids-text font-size="24" type="h2">Parent Modal</ids-text>
</ids-layout-grid>
<ids-layout-grid>
<p>This is the Parent IDS Modal</p>
</ids-layout-grid>
<ids-layout-grid auto="true">
<ids-layout-grid-cell>
<ids-button id="parent-modal-close-btn" type="secondary">
<span slot="text">Close</span>
</ids-button>
<ids-button id="nested-modal-trigger-btn" type="primary">
<span slot="text">Open Another</span>
</ids-button>
</ids-layout-grid-cell>
</ids-layout-grid>
</ids-modal>

<ids-modal id="nested-modal">
<ids-layout-grid>
<ids-text font-size="24" type="h2">Nested Modal</ids-text>
</ids-layout-grid>
<ids-layout-grid>
<p>This is the Nested IDS Modal</p>
</ids-layout-grid>
<ids-layout-grid auto="true">
<ids-layout-grid-cell>
<ids-button id="nested-modal-close-btn" type="secondary">
<span slot="text">Close</span>
</ids-button>
</ids-layout-grid-cell>
</ids-layout-grid>
</ids-modal>

<ids-layout-grid>
<ids-text font-size="12" type="h1">Modal</ids-text>
</ids-layout-grid>
<ids-layout-grid auto="true">
<ids-layout-grid-cell>
<ids-button id="parent-modal-trigger-btn" type="secondary">
<span slot="text">Trigger a Modal</span>
</ids-button>
</ids-layout-grid-cell>
</ids-layout-grid>


{{> ../layouts/footer.html }}
44 changes: 44 additions & 0 deletions app/ids-modal/nested.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import IdsModal from '../../src/ids-modal/ids-modal';
import IdsButton from '../../src/ids-button/ids-button';

document.addEventListener('DOMContentLoaded', () => {
const parentTriggerId = '#parent-modal-trigger-btn';
const parentTriggerBtn = document.querySelector(parentTriggerId);
const parentModal = document.querySelector('#parent-modal');
const parentModalCloseBtn = parentModal.querySelector('ids-button');

const nestedTriggerId = '#nested-modal-trigger-btn';
const nestedTriggerBtn = document.querySelector(nestedTriggerId);
const nestedModal = document.querySelector('#nested-modal');
const nestedModalCloseBtn = nestedModal.querySelector('ids-button');

// Links the Modals to their trigger buttons
parentModal.target = parentTriggerBtn;
nestedModal.target = nestedTriggerBtn;

// Disable the trigger buttons when showing their Modals.
parentModal.addEventListener('beforeshow', () => {
parentTriggerBtn.disabled = true;
return true;
});
nestedModal.addEventListener('beforeshow', () => {
nestedTriggerBtn.disabled = true;
return true;
});

// Close the modals when their "close" buttons are clicked
parentModalCloseBtn.addEventListener('click', () => {
parentModal.hide();
});
nestedModalCloseBtn.addEventListener('click', () => {
nestedModal.hide();
});

// When the modals are fully hidden, re-enable their trigger buttons
parentModal.addEventListener('hide', () => {
parentTriggerBtn.disabled = false;
});
nestedModal.addEventListener('hide', () => {
nestedTriggerBtn.disabled = false;
});
});
33 changes: 33 additions & 0 deletions app/ids-modal/visible.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{{> ../layouts/head.html }}

<ids-modal id="my-modal" visible="true">
<ids-layout-grid>
<ids-text font-size="24" type="h2">Active IDS Modal</ids-text>
</ids-layout-grid>
<ids-layout-grid>
<p>This is an active IDS Modal component</p>
</ids-layout-grid>
<ids-layout-grid auto="true">
<ids-layout-grid-cell>
<ids-button id="modal-close-btn" type="secondary">
<span slot="text">OK</span>
</ids-button>
</ids-layout-grid-cell>
</ids-layout-grid>
</ids-modal>

<ids-layout-grid>
<ids-text font-size="12" type="h1">Modal (visibility example)</ids-text>
</ids-layout-grid>
<ids-layout-grid>
<ids-text>This Modal example will be visible when the page loads</ids-text>
</ids-layout-grid>
<ids-layout-grid auto="true">
<ids-layout-grid-cell>
<ids-button id="modal-trigger-btn" type="secondary">
<span slot="text">Trigger a Modal</span>
</ids-button>
</ids-layout-grid-cell>
</ids-layout-grid>

{{> ../layouts/footer.html }}
28 changes: 28 additions & 0 deletions app/ids-modal/visible.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import IdsModal from '../../src/ids-modal/ids-modal';
import IdsButton from '../../src/ids-button/ids-button';

document.addEventListener('DOMContentLoaded', () => {
const triggerId = '#modal-trigger-btn';
const triggerBtn = document.querySelector(triggerId);
const modal = document.querySelector('ids-modal');
const modalCloseBtn = modal.querySelector('ids-button');

// Links the Modal to its trigger button
modal.target = triggerBtn;

// Disable the trigger button when showing the Modal.
modal.addEventListener('beforeshow', () => {
triggerBtn.disabled = true;
return true;
});

// Close the modal when its inner button is clicked
modalCloseBtn.addEventListener('click', () => {
modal.hide();
});

// After the modal is done hiding, re-enable its trigger button.
modal.addEventListener('hide', () => {
triggerBtn.disabled = false;
});
});
1 change: 1 addition & 0 deletions app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
{{> ids-upload/example.html }}
{{> ids-textarea/example.html }}
{{> ids-popup/example.html }}
{{> ids-modal/example.html }}
{{> ids-tooltip/example.html }}
{{> ids-toolbar/example.html }}
{{> ids-progress/example.html }}
Expand Down
2 changes: 2 additions & 0 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import IdsCounts from '../src/ids-counts/ids-counts';
import IdsContainer from '../src/ids-container/ids-container';
import IdsThemeSwitcher from '../src/ids-theme-switcher/ids-theme-switcher';
import IdsWizard, { IdsWizardStep } from '../src/ids-wizard';
import IdsModal, { IdsOverlay } from '../src/ids-modal';

// Import Example Code

Expand All @@ -48,6 +49,7 @@ import './ids-icon/index';
import './ids-input/example';
import './ids-input/test-validation-message';
import './ids-mask/example';
import './ids-modal/example';
import './ids-progress/example';
import './ids-upload-advanced/example';
import './ids-popup/index';
Expand Down
5 changes: 5 additions & 0 deletions doc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
- Now exists as its own component
- Markup is `<ids-menu-button></ids-menu-button>`
- Implicitly linked to a menu by using `menu="my-menu"` CSS selector attribute, or direct element reference in JS
- `[Modal]` The Modal is now a web component called ids-modal ([WC#118](https://github.com/infor-design/enterprise-wc/issues/118))
- All content inside the modal boundary is now user-defined by slot
- Triggering element for the modal is now configurable with the `target` prop
- Events are now just plain JS events
- Markup has been changed to custom element `<ids-modal></ids-modal>`
- `[Popup]` Added the Popup WebComponent. ([#4259](https://github.com/infor-design/enterprise/issues/4259))
- This is the new base component to be used for building Popupmenu, Tooltip, Modal, and any other component that requires placement of a fixed-position element.
- If using properties/settings, these are now attributes: x, y, align, alignX, alignY, alignEdge, alignTarget, animated, visible.
Expand Down
2 changes: 1 addition & 1 deletion doc/CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Will get a checkbox at minimum viable product. The rest of the details are cover
- [ ] Masthead (ids-masthead)
- [x] MenuButton (ids-menu-button)
- [ ] Message (ids-message)
- [ ] Modal (ids-modal)
- [x] Modal (ids-modal)
- [ ] Monthview (ids-month-view)
- [ ] Multiselect (ids-multi-select)
- [ ] Notification (ids-notification)
Expand Down
2 changes: 2 additions & 0 deletions src/ids-base/ids-constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const props = {
ACCEPT: 'accept',
ALTERNATE_ROW_SHADING: 'alternate-row-shading',
ANIMATED: 'animated',
ANIMATION_STYLE: 'animation-style',
ALIGN: 'align',
APPEARANCE: 'appearance',
AUDIBLE: 'audible',
Expand Down Expand Up @@ -71,6 +72,7 @@ export const props = {
MULTIPLE: 'multiple',
NO_MARGINS: 'no-margins',
NO_TEXT_ELLIPSIS: 'no-text-ellipsis',
OPACTIY: 'opacity',
OVERFLOW: 'overflow',
PLACEHOLDER: 'placeholder',
PLACEMENT: 'placement',
Expand Down
4 changes: 4 additions & 0 deletions src/ids-base/ids-debouncer.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** prevents a function that runs on intervals from running too frequently */
declare function debounce(func: CallableFunction, duration?: number, execAsap?: boolean): void;

export default debounce;
44 changes: 44 additions & 0 deletions src/ids-base/ids-debouncer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import renderLoop from '../ids-render-loop/ids-render-loop-global';
import IdsRenderLoopItem from '../ids-render-loop/ids-render-loop-item';

/**
* Debounces a function, preventing running the function too frequently while looping.
* This is ideal for functions that run on intervals.
* @param {Function} func the callback function to be run on a stagger.
* @param {number} [duration] the amount of time in CPU ticks to delay.
* @param {boolean} [execAsap] if true, executes the callback immediately
* instead of waiting for the threshold to complete.
* @returns {void}
*/
/* istanbul ignore next */
export default function debounce(func, duration = 60, execAsap) {
let timeout;

// Clears the render loop item
const destroyTimeout = () => {
timeout.destroy(true);
timeout = null;
};

return function debounced(...args) {
const obj = this;
const timeoutCallback = () => {
if (!execAsap) {
func.apply(obj, args);
}
destroyTimeout();
};

if (timeout) {
destroyTimeout();
} else if (execAsap) {
func.apply(obj, args);
}

timeout = new IdsRenderLoopItem({
duration,
timeoutCallback
});
renderLoop.register(timeout);
};
}
37 changes: 37 additions & 0 deletions src/ids-base/ids-dom-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,43 @@ const IdsDOMUtils = {
*/
getClosestRootNode(node) {
return IdsDOMUtils.getClosestShadow(node)?.host?.parentNode || document;
},

/**
* Changes a CSS property with a transition,
* @param {HTMLElement} el the element to act on
* @param {string} property the CSS property with an attached transition to manipulate
* @param {any} value the target CSS value
* @returns {Promise} fulfulled when the CSS transition completes
*/
transitionToPromise(el, property, value) {
return new Promise((resolve) => {
el.style[property] = value;
const transitionEnded = /* istanbul ignore next */ (e) => {
if (e.propertyName !== property) return;
el.removeEventListener('transitionend', transitionEnded);
resolve();
};
el.addEventListener('transitionend', transitionEnded);
});
},

/**
* Similar to `transitionToPromise`, but simply waits for the specified property's `transitionend`
* event to complete (allows the user to change the property outside the promise)
* @param {HTMLElement} el the element to act on
* @param {string} property the CSS property used to qualify the correct transitionend event
* @returns {Promise} fulfulled when the CSS transition completes
*/
waitForTransitionEnd(el, property) {
return new Promise((resolve) => {
const transitionEnded = /* istanbul ignore next */ (e) => {
if (e.propertyName !== property) return;
el.removeEventListener('transitionend', transitionEnded);
resolve();
};
el.addEventListener('transitionend', transitionEnded);
});
}
};

Expand Down
2 changes: 2 additions & 0 deletions src/ids-base/ids-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,13 @@ class IdsElement extends HTMLElement {
this.appendStyles();
template.innerHTML = this.template();
this.shadowRoot?.appendChild(template.content.cloneNode(true));

/** @type {any} */
this.container = this.shadowRoot?.querySelector(`.${this.name}`);
if (!this.container) {
this.container = this.shadowRoot?.firstElementChild;
}

// Remove any close hidden element to avoid FOUC
this.closest('div[role="main"][hidden]')?.removeAttribute('hidden');
this.closest('ids-container')?.removeAttribute('hidden');
Expand Down
3 changes: 3 additions & 0 deletions src/ids-base/ids-keyboard-mixin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export class IdsKeyboardMixin {
/** Add a listener for a key or key code combination */
listen(keycode: Array<unknown> | string, elem: HTMLElement, callback: () => void): void;

/** Remove a listener for a key */
unlisten(key: string): Map<unknown, unknown>

/** Remove all handlers and clear memory */
detachAllListeners(): void;
}
Loading

0 comments on commit 9beee53

Please sign in to comment.