@stimulus-plumbers/controllers 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +144 -0
- package/dist/stimulus-plumbers-controllers.es.js +1459 -0
- package/dist/stimulus-plumbers-controllers.umd.js +1 -0
- package/package.json +57 -0
- package/src/aria.js +173 -0
- package/src/controllers/auto_resize_controller.js +17 -0
- package/src/controllers/calendar_month_controller.js +100 -0
- package/src/controllers/calendar_month_observer_controller.js +24 -0
- package/src/controllers/datepicker_controller.js +101 -0
- package/src/controllers/dismisser_controller.js +10 -0
- package/src/controllers/flipper_controller.js +33 -0
- package/src/controllers/form-field_controller.js +77 -0
- package/src/controllers/modal_controller.js +104 -0
- package/src/controllers/panner_controller.js +10 -0
- package/src/controllers/password_reveal_controller.js +9 -0
- package/src/controllers/popover_controller.js +76 -0
- package/src/controllers/visibility_controller.js +32 -0
- package/src/focus.js +128 -0
- package/src/index.js +23 -0
- package/src/keyboard.js +92 -0
- package/src/plumbers/calendar.js +399 -0
- package/src/plumbers/content_loader.js +134 -0
- package/src/plumbers/dismisser.js +82 -0
- package/src/plumbers/flipper.js +272 -0
- package/src/plumbers/index.js +10 -0
- package/src/plumbers/plumber/index.js +110 -0
- package/src/plumbers/plumber/support.js +101 -0
- package/src/plumbers/shifter.js +164 -0
- package/src/plumbers/visibility.js +136 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import Plumber from './plumber';
|
|
2
|
+
import { visibilityConfig } from './plumber/support';
|
|
3
|
+
|
|
4
|
+
const defaultOptions = {
|
|
5
|
+
visibility: 'visibility',
|
|
6
|
+
onShown: 'shown',
|
|
7
|
+
onHidden: 'hidden',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export class Visibility extends Plumber {
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new Visibility plumber instance.
|
|
13
|
+
* @param {Object} controller - Stimulus controller instance
|
|
14
|
+
* @param {Object} [options] - Configuration options
|
|
15
|
+
* @param {string} [options.visibility='visibility'] - Namespace for visibility helpers
|
|
16
|
+
* @param {string} [options.onShown='shown'] - Method name on plumber instance called after showing
|
|
17
|
+
* @param {string} [options.onHidden='hidden'] - Method name on plumber instance called after hiding
|
|
18
|
+
*/
|
|
19
|
+
constructor(controller, options = {}) {
|
|
20
|
+
const { visibility, onShown, onHidden, activator } = Object.assign({}, defaultOptions, options);
|
|
21
|
+
|
|
22
|
+
const namespace = typeof visibility === 'string' ? visibility : defaultOptions.namespace;
|
|
23
|
+
const resolver = typeof options.visible === 'string' ? options.visible : 'isVisible';
|
|
24
|
+
if (typeof options.visible !== 'boolean' || options.visible) {
|
|
25
|
+
options.visible = `${namespace}.${resolver}`;
|
|
26
|
+
}
|
|
27
|
+
super(controller, options);
|
|
28
|
+
|
|
29
|
+
this.visibility = namespace;
|
|
30
|
+
this.visibilityResolver = resolver;
|
|
31
|
+
this.onShown = onShown;
|
|
32
|
+
this.onHidden = onHidden;
|
|
33
|
+
this.activator = activator instanceof HTMLElement ? activator : null;
|
|
34
|
+
|
|
35
|
+
this.enhance();
|
|
36
|
+
|
|
37
|
+
if (this.element instanceof HTMLElement) this.activate(this.isVisible(this.element));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Checks if a target element is visible.
|
|
42
|
+
* @param {HTMLElement} target - Element to check
|
|
43
|
+
* @returns {boolean} True if element is visible
|
|
44
|
+
*/
|
|
45
|
+
isVisible(target) {
|
|
46
|
+
if (!(target instanceof HTMLElement)) return false;
|
|
47
|
+
|
|
48
|
+
const hiddenClass = visibilityConfig.hiddenClass;
|
|
49
|
+
return hiddenClass ? !target.classList.contains(hiddenClass) : !target.hasAttribute('hidden');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Toggles element visibility using class or hidden attribute.
|
|
54
|
+
* @param {HTMLElement} target - Element to toggle
|
|
55
|
+
* @param {boolean} visible - True to show, false to hide
|
|
56
|
+
*/
|
|
57
|
+
toggle(target, visible) {
|
|
58
|
+
if (!(target instanceof HTMLElement)) return;
|
|
59
|
+
|
|
60
|
+
const hiddenClass = visibilityConfig.hiddenClass;
|
|
61
|
+
if (hiddenClass) {
|
|
62
|
+
if (visible) target.classList.remove(hiddenClass);
|
|
63
|
+
else target.classList.add(hiddenClass);
|
|
64
|
+
} else {
|
|
65
|
+
if (visible) target.removeAttribute('hidden');
|
|
66
|
+
else target.setAttribute('hidden', true);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Sets aria-expanded on the activator element.
|
|
72
|
+
* @param {boolean} isExpanded - True to mark as expanded, false to mark as collapsed
|
|
73
|
+
*/
|
|
74
|
+
activate(isExpanded) {
|
|
75
|
+
if (this.activator) this.activator.setAttribute('aria-expanded', isExpanded ? 'true' : 'false');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Shows the element and dispatches show events.
|
|
80
|
+
* @returns {Promise<void>}
|
|
81
|
+
*/
|
|
82
|
+
async show() {
|
|
83
|
+
if (!(this.element instanceof HTMLElement) || this.isVisible(this.element)) return;
|
|
84
|
+
|
|
85
|
+
this.dispatch('show');
|
|
86
|
+
this.toggle(this.element, true);
|
|
87
|
+
this.activate(true);
|
|
88
|
+
|
|
89
|
+
await this.awaitCallback(this.onShown, { target: this.element });
|
|
90
|
+
this.dispatch('shown');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Hides the element and dispatches hide events.
|
|
95
|
+
* @returns {Promise<void>}
|
|
96
|
+
*/
|
|
97
|
+
async hide() {
|
|
98
|
+
if (!(this.element instanceof HTMLElement) || !this.isVisible(this.element)) return;
|
|
99
|
+
|
|
100
|
+
this.dispatch('hide');
|
|
101
|
+
this.toggle(this.element, false);
|
|
102
|
+
this.activate(false);
|
|
103
|
+
|
|
104
|
+
await this.awaitCallback(this.onHidden, { target: this.element });
|
|
105
|
+
this.dispatch('hidden');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
enhance() {
|
|
109
|
+
const context = this;
|
|
110
|
+
const helpers = {
|
|
111
|
+
show: context.show.bind(context),
|
|
112
|
+
hide: context.hide.bind(context),
|
|
113
|
+
};
|
|
114
|
+
Object.defineProperty(helpers, 'visible', {
|
|
115
|
+
get() {
|
|
116
|
+
return context.isVisible(context.element);
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
Object.defineProperty(helpers, this.visibilityResolver, {
|
|
120
|
+
value: context.isVisible.bind(context),
|
|
121
|
+
});
|
|
122
|
+
Object.defineProperty(this.controller, this.visibility, {
|
|
123
|
+
get() {
|
|
124
|
+
return helpers;
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Factory function to create and attach a Visibility plumber to a controller.
|
|
132
|
+
* @param {Object} controller - Stimulus controller instance
|
|
133
|
+
* @param {Object} [options] - Configuration options
|
|
134
|
+
* @returns {Visibility} Visibility plumber instance
|
|
135
|
+
*/
|
|
136
|
+
export const attachVisibility = (controller, options) => new Visibility(controller, options);
|