@bedlamhotel/attrmanager 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.
@@ -0,0 +1,138 @@
1
+ /*! attr-manager 0.2.0 — © Christopher Torgalson */
2
+ 'use strict';
3
+
4
+ /**
5
+ * A class used to create and/or enforce HTMLElement attribute values.
6
+ */
7
+ class AttrManager {
8
+ el;
9
+ /** Unique ID for self-removal from `restorers` array. */
10
+ id;
11
+ /** An array of the attributes under management in NormalizedAttr form. */
12
+ items = [];
13
+ /** An array of the attribute values (used to restore initial DOM state). */
14
+ original = [];
15
+ /** A var used to track the state of the attributes under management. */
16
+ currentState = false;
17
+ /** Optional reference to the restorer array for self-removal. */
18
+ restorers;
19
+ /**
20
+ * Generates a unique ID for this instance.
21
+ */
22
+ static createId() {
23
+ return Math.random().toString(36).slice(2, 7);
24
+ }
25
+ /**
26
+ * Constructs a new AttrManager instance.
27
+ *
28
+ * @param el
29
+ * The HTMLElement to manage.
30
+ * @param config
31
+ * The attribute configuration.
32
+ * @param restorers
33
+ * Optional restorer array for lifecycle management.
34
+ */
35
+ constructor(el, config, restorers) {
36
+ this.el = el;
37
+ let hasExplicitInitial = false;
38
+ // Generate unique ID for self-removal from restorers
39
+ this.id = AttrManager.createId();
40
+ for (const [name, { whenTrue: trueValue, whenFalse, initial, fixed },] of Object.entries(config)) {
41
+ if (trueValue === undefined) {
42
+ throw new Error("AttrManager: each attribute must supply a `whenTrue` value.");
43
+ }
44
+ if (initial !== undefined &&
45
+ !["whenTrue", "whenFalse", null].includes(initial)) {
46
+ throw new Error("AttrManager: if attributes supply an `initial` value, it must be one of `whenTrue`, `whenFalse`, or `null`.");
47
+ }
48
+ const originalVal = el.getAttribute(name);
49
+ this.original.push([name, originalVal]);
50
+ const falseValue = whenFalse !== undefined ? whenFalse : originalVal;
51
+ this.items.push({ name, trueValue, falseValue, fixed: !!fixed });
52
+ if (initial !== undefined) {
53
+ this.applyValue(name, initial === "whenTrue" ? trueValue : falseValue);
54
+ if (!hasExplicitInitial) {
55
+ this.currentState = initial === "whenTrue";
56
+ hasExplicitInitial = true;
57
+ }
58
+ }
59
+ }
60
+ // Register restorer with ID for self-removal
61
+ if (restorers) {
62
+ this.restorers = restorers;
63
+ restorers.push({
64
+ id: this.id,
65
+ restore: () => this.restore(),
66
+ });
67
+ }
68
+ }
69
+ /**
70
+ * Toggles state of attributes managed by this instance.
71
+ *
72
+ * @param condition
73
+ * The condition to set. If omitted, toggles the current state.
74
+ */
75
+ toggle(condition) {
76
+ this.currentState = condition ?? !this.currentState;
77
+ for (const { name, trueValue, falseValue, fixed } of this.items) {
78
+ if (fixed) {
79
+ continue;
80
+ }
81
+ this.applyValue(name, this.currentState ? trueValue : falseValue);
82
+ }
83
+ }
84
+ /**
85
+ * Restores original state of attributes.
86
+ *
87
+ * @param teardown
88
+ * If `true` (default), also clears internal state and self-removes from
89
+ * `restorers`.
90
+ */
91
+ restore(teardown = false) {
92
+ for (const [name, value] of this.original) {
93
+ this.applyValue(name, value);
94
+ }
95
+ if (teardown) {
96
+ this.destroy();
97
+ }
98
+ }
99
+ /**
100
+ * Clears internal state and self-removes from `restorers`.
101
+ *
102
+ * Use this to clean up state without affecting the DOM.
103
+ */
104
+ destroy() {
105
+ // Remove self from restorers if registered
106
+ if (this.restorers) {
107
+ const index = this.restorers.findIndex((r) => r.id === this.id);
108
+ if (index > -1) {
109
+ this.restorers.splice(index, 1);
110
+ }
111
+ }
112
+ // Clear all state
113
+ this.items = [];
114
+ this.original = [];
115
+ this.currentState = false;
116
+ }
117
+ /**
118
+ * Handles actual DOM attribute manipulation for toggle(), restore().
119
+ *
120
+ * @param name
121
+ * The attribute name.
122
+ * @param value
123
+ * The value to set. Pass `null` to remove the attribute.
124
+ */
125
+ applyValue(name, value) {
126
+ if (this.el.getAttribute(name) === value) {
127
+ return;
128
+ }
129
+ if (value === null) {
130
+ this.el.removeAttribute(name);
131
+ }
132
+ else {
133
+ this.el.setAttribute(name, value);
134
+ }
135
+ }
136
+ }
137
+
138
+ module.exports = AttrManager;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * A type used to define possible values for AttrConfig's `initial` prop.
3
+ */
4
+ export type AttrInitialValue = "whenTrue" | "whenFalse" | null;
5
+ /**
6
+ * A type used to define the config option used by the constructor.
7
+ */
8
+ export type AttrConfig = Record<string, {
9
+ /** The value set for an attribute when currentState is `true`. */
10
+ whenTrue: string | null;
11
+ /** The value set for an attribute when currentState is `false`. */
12
+ whenFalse?: string | null;
13
+ /** The value set for an attribute in the constructor. */
14
+ initial?: AttrInitialValue;
15
+ /** Whether this attribute will be ignored by `.toggle()`. */
16
+ fixed?: boolean;
17
+ }>;
18
+ /**
19
+ * An internal type: guarantees `falseValue` is never undefined.
20
+ */
21
+ export interface NormalizedAttr {
22
+ /** The value set for an attribute when currentState is `true`. */
23
+ trueValue: string | null;
24
+ /** The value set for an attribute when currentState is `false`. */
25
+ falseValue: string | null;
26
+ /** The name of the attribute under management. */
27
+ name: string;
28
+ /** Whether this attribute will be ignored by `.toggle()`. */
29
+ fixed: boolean;
30
+ }
31
+ /**
32
+ * An entry in the `restorers` array.
33
+ */
34
+ export interface RestorerEntry {
35
+ /** Unique ID for self-removal. */
36
+ id: string;
37
+ /** Restore method. */
38
+ restore: () => void;
39
+ }
40
+ /**
41
+ * A class used to create and/or enforce HTMLElement attribute values.
42
+ */
43
+ export default class AttrManager {
44
+ private readonly el;
45
+ /** Unique ID for self-removal from `restorers` array. */
46
+ private readonly id;
47
+ /** An array of the attributes under management in NormalizedAttr form. */
48
+ private items;
49
+ /** An array of the attribute values (used to restore initial DOM state). */
50
+ private original;
51
+ /** A var used to track the state of the attributes under management. */
52
+ private currentState;
53
+ /** Optional reference to the restorer array for self-removal. */
54
+ private readonly restorers?;
55
+ /**
56
+ * Generates a unique ID for this instance.
57
+ */
58
+ private static createId;
59
+ /**
60
+ * Constructs a new AttrManager instance.
61
+ *
62
+ * @param el
63
+ * The HTMLElement to manage.
64
+ * @param config
65
+ * The attribute configuration.
66
+ * @param restorers
67
+ * Optional restorer array for lifecycle management.
68
+ */
69
+ constructor(el: HTMLElement, config: AttrConfig, restorers?: RestorerEntry[]);
70
+ /**
71
+ * Toggles state of attributes managed by this instance.
72
+ *
73
+ * @param condition
74
+ * The condition to set. If omitted, toggles the current state.
75
+ */
76
+ toggle(condition?: boolean): void;
77
+ /**
78
+ * Restores original state of attributes.
79
+ *
80
+ * @param teardown
81
+ * If `true` (default), also clears internal state and self-removes from
82
+ * `restorers`.
83
+ */
84
+ restore(teardown?: boolean): void;
85
+ /**
86
+ * Clears internal state and self-removes from `restorers`.
87
+ *
88
+ * Use this to clean up state without affecting the DOM.
89
+ */
90
+ destroy(): void;
91
+ /**
92
+ * Handles actual DOM attribute manipulation for toggle(), restore().
93
+ *
94
+ * @param name
95
+ * The attribute name.
96
+ * @param value
97
+ * The value to set. Pass `null` to remove the attribute.
98
+ */
99
+ private applyValue;
100
+ }
@@ -0,0 +1,136 @@
1
+ /*! attr-manager 0.2.0 — © Christopher Torgalson */
2
+ /**
3
+ * A class used to create and/or enforce HTMLElement attribute values.
4
+ */
5
+ class AttrManager {
6
+ el;
7
+ /** Unique ID for self-removal from `restorers` array. */
8
+ id;
9
+ /** An array of the attributes under management in NormalizedAttr form. */
10
+ items = [];
11
+ /** An array of the attribute values (used to restore initial DOM state). */
12
+ original = [];
13
+ /** A var used to track the state of the attributes under management. */
14
+ currentState = false;
15
+ /** Optional reference to the restorer array for self-removal. */
16
+ restorers;
17
+ /**
18
+ * Generates a unique ID for this instance.
19
+ */
20
+ static createId() {
21
+ return Math.random().toString(36).slice(2, 7);
22
+ }
23
+ /**
24
+ * Constructs a new AttrManager instance.
25
+ *
26
+ * @param el
27
+ * The HTMLElement to manage.
28
+ * @param config
29
+ * The attribute configuration.
30
+ * @param restorers
31
+ * Optional restorer array for lifecycle management.
32
+ */
33
+ constructor(el, config, restorers) {
34
+ this.el = el;
35
+ let hasExplicitInitial = false;
36
+ // Generate unique ID for self-removal from restorers
37
+ this.id = AttrManager.createId();
38
+ for (const [name, { whenTrue: trueValue, whenFalse, initial, fixed },] of Object.entries(config)) {
39
+ if (trueValue === undefined) {
40
+ throw new Error("AttrManager: each attribute must supply a `whenTrue` value.");
41
+ }
42
+ if (initial !== undefined &&
43
+ !["whenTrue", "whenFalse", null].includes(initial)) {
44
+ throw new Error("AttrManager: if attributes supply an `initial` value, it must be one of `whenTrue`, `whenFalse`, or `null`.");
45
+ }
46
+ const originalVal = el.getAttribute(name);
47
+ this.original.push([name, originalVal]);
48
+ const falseValue = whenFalse !== undefined ? whenFalse : originalVal;
49
+ this.items.push({ name, trueValue, falseValue, fixed: !!fixed });
50
+ if (initial !== undefined) {
51
+ this.applyValue(name, initial === "whenTrue" ? trueValue : falseValue);
52
+ if (!hasExplicitInitial) {
53
+ this.currentState = initial === "whenTrue";
54
+ hasExplicitInitial = true;
55
+ }
56
+ }
57
+ }
58
+ // Register restorer with ID for self-removal
59
+ if (restorers) {
60
+ this.restorers = restorers;
61
+ restorers.push({
62
+ id: this.id,
63
+ restore: () => this.restore(),
64
+ });
65
+ }
66
+ }
67
+ /**
68
+ * Toggles state of attributes managed by this instance.
69
+ *
70
+ * @param condition
71
+ * The condition to set. If omitted, toggles the current state.
72
+ */
73
+ toggle(condition) {
74
+ this.currentState = condition ?? !this.currentState;
75
+ for (const { name, trueValue, falseValue, fixed } of this.items) {
76
+ if (fixed) {
77
+ continue;
78
+ }
79
+ this.applyValue(name, this.currentState ? trueValue : falseValue);
80
+ }
81
+ }
82
+ /**
83
+ * Restores original state of attributes.
84
+ *
85
+ * @param teardown
86
+ * If `true` (default), also clears internal state and self-removes from
87
+ * `restorers`.
88
+ */
89
+ restore(teardown = false) {
90
+ for (const [name, value] of this.original) {
91
+ this.applyValue(name, value);
92
+ }
93
+ if (teardown) {
94
+ this.destroy();
95
+ }
96
+ }
97
+ /**
98
+ * Clears internal state and self-removes from `restorers`.
99
+ *
100
+ * Use this to clean up state without affecting the DOM.
101
+ */
102
+ destroy() {
103
+ // Remove self from restorers if registered
104
+ if (this.restorers) {
105
+ const index = this.restorers.findIndex((r) => r.id === this.id);
106
+ if (index > -1) {
107
+ this.restorers.splice(index, 1);
108
+ }
109
+ }
110
+ // Clear all state
111
+ this.items = [];
112
+ this.original = [];
113
+ this.currentState = false;
114
+ }
115
+ /**
116
+ * Handles actual DOM attribute manipulation for toggle(), restore().
117
+ *
118
+ * @param name
119
+ * The attribute name.
120
+ * @param value
121
+ * The value to set. Pass `null` to remove the attribute.
122
+ */
123
+ applyValue(name, value) {
124
+ if (this.el.getAttribute(name) === value) {
125
+ return;
126
+ }
127
+ if (value === null) {
128
+ this.el.removeAttribute(name);
129
+ }
130
+ else {
131
+ this.el.setAttribute(name, value);
132
+ }
133
+ }
134
+ }
135
+
136
+ export { AttrManager as default };
@@ -0,0 +1,2 @@
1
+ /*! attr-manager 0.2.0 — © Christopher Torgalson */
2
+ class AttrManager{el;id;items=[];original=[];currentState=!1;restorers;static createId(){return Math.random().toString(36).slice(2,7)}constructor(t,e,r){this.el=t;let i=!1;this.id=AttrManager.createId();for(const[r,{whenTrue:s,whenFalse:a,initial:n,fixed:l}]of Object.entries(e)){if(void 0===s)throw new Error("AttrManager: each attribute must supply a `whenTrue` value.");if(void 0!==n&&!["whenTrue","whenFalse",null].includes(n))throw new Error("AttrManager: if attributes supply an `initial` value, it must be one of `whenTrue`, `whenFalse`, or `null`.");const e=t.getAttribute(r);this.original.push([r,e]);const o=void 0!==a?a:e;this.items.push({name:r,trueValue:s,falseValue:o,fixed:!!l}),void 0!==n&&(this.applyValue(r,"whenTrue"===n?s:o),i||(this.currentState="whenTrue"===n,i=!0))}r&&(this.restorers=r,r.push({id:this.id,restore:()=>this.restore()}))}toggle(t){this.currentState=t??!this.currentState;for(const{name:t,trueValue:e,falseValue:r,fixed:i}of this.items)i||this.applyValue(t,this.currentState?e:r)}restore(t=!1){for(const[t,e]of this.original)this.applyValue(t,e);t&&this.destroy()}destroy(){if(this.restorers){const t=this.restorers.findIndex(t=>t.id===this.id);t>-1&&this.restorers.splice(t,1)}this.items=[],this.original=[],this.currentState=!1}applyValue(t,e){this.el.getAttribute(t)!==e&&(null===e?this.el.removeAttribute(t):this.el.setAttribute(t,e))}}export{AttrManager as default};
@@ -0,0 +1,144 @@
1
+ /*! attr-manager 0.2.0 — © Christopher Torgalson */
2
+ (function (global, factory) {
3
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4
+ typeof define === 'function' && define.amd ? define(factory) :
5
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.AttrManager = factory());
6
+ })(this, (function () { 'use strict';
7
+
8
+ /**
9
+ * A class used to create and/or enforce HTMLElement attribute values.
10
+ */
11
+ class AttrManager {
12
+ el;
13
+ /** Unique ID for self-removal from `restorers` array. */
14
+ id;
15
+ /** An array of the attributes under management in NormalizedAttr form. */
16
+ items = [];
17
+ /** An array of the attribute values (used to restore initial DOM state). */
18
+ original = [];
19
+ /** A var used to track the state of the attributes under management. */
20
+ currentState = false;
21
+ /** Optional reference to the restorer array for self-removal. */
22
+ restorers;
23
+ /**
24
+ * Generates a unique ID for this instance.
25
+ */
26
+ static createId() {
27
+ return Math.random().toString(36).slice(2, 7);
28
+ }
29
+ /**
30
+ * Constructs a new AttrManager instance.
31
+ *
32
+ * @param el
33
+ * The HTMLElement to manage.
34
+ * @param config
35
+ * The attribute configuration.
36
+ * @param restorers
37
+ * Optional restorer array for lifecycle management.
38
+ */
39
+ constructor(el, config, restorers) {
40
+ this.el = el;
41
+ let hasExplicitInitial = false;
42
+ // Generate unique ID for self-removal from restorers
43
+ this.id = AttrManager.createId();
44
+ for (const [name, { whenTrue: trueValue, whenFalse, initial, fixed },] of Object.entries(config)) {
45
+ if (trueValue === undefined) {
46
+ throw new Error("AttrManager: each attribute must supply a `whenTrue` value.");
47
+ }
48
+ if (initial !== undefined &&
49
+ !["whenTrue", "whenFalse", null].includes(initial)) {
50
+ throw new Error("AttrManager: if attributes supply an `initial` value, it must be one of `whenTrue`, `whenFalse`, or `null`.");
51
+ }
52
+ const originalVal = el.getAttribute(name);
53
+ this.original.push([name, originalVal]);
54
+ const falseValue = whenFalse !== undefined ? whenFalse : originalVal;
55
+ this.items.push({ name, trueValue, falseValue, fixed: !!fixed });
56
+ if (initial !== undefined) {
57
+ this.applyValue(name, initial === "whenTrue" ? trueValue : falseValue);
58
+ if (!hasExplicitInitial) {
59
+ this.currentState = initial === "whenTrue";
60
+ hasExplicitInitial = true;
61
+ }
62
+ }
63
+ }
64
+ // Register restorer with ID for self-removal
65
+ if (restorers) {
66
+ this.restorers = restorers;
67
+ restorers.push({
68
+ id: this.id,
69
+ restore: () => this.restore(),
70
+ });
71
+ }
72
+ }
73
+ /**
74
+ * Toggles state of attributes managed by this instance.
75
+ *
76
+ * @param condition
77
+ * The condition to set. If omitted, toggles the current state.
78
+ */
79
+ toggle(condition) {
80
+ this.currentState = condition ?? !this.currentState;
81
+ for (const { name, trueValue, falseValue, fixed } of this.items) {
82
+ if (fixed) {
83
+ continue;
84
+ }
85
+ this.applyValue(name, this.currentState ? trueValue : falseValue);
86
+ }
87
+ }
88
+ /**
89
+ * Restores original state of attributes.
90
+ *
91
+ * @param teardown
92
+ * If `true` (default), also clears internal state and self-removes from
93
+ * `restorers`.
94
+ */
95
+ restore(teardown = false) {
96
+ for (const [name, value] of this.original) {
97
+ this.applyValue(name, value);
98
+ }
99
+ if (teardown) {
100
+ this.destroy();
101
+ }
102
+ }
103
+ /**
104
+ * Clears internal state and self-removes from `restorers`.
105
+ *
106
+ * Use this to clean up state without affecting the DOM.
107
+ */
108
+ destroy() {
109
+ // Remove self from restorers if registered
110
+ if (this.restorers) {
111
+ const index = this.restorers.findIndex((r) => r.id === this.id);
112
+ if (index > -1) {
113
+ this.restorers.splice(index, 1);
114
+ }
115
+ }
116
+ // Clear all state
117
+ this.items = [];
118
+ this.original = [];
119
+ this.currentState = false;
120
+ }
121
+ /**
122
+ * Handles actual DOM attribute manipulation for toggle(), restore().
123
+ *
124
+ * @param name
125
+ * The attribute name.
126
+ * @param value
127
+ * The value to set. Pass `null` to remove the attribute.
128
+ */
129
+ applyValue(name, value) {
130
+ if (this.el.getAttribute(name) === value) {
131
+ return;
132
+ }
133
+ if (value === null) {
134
+ this.el.removeAttribute(name);
135
+ }
136
+ else {
137
+ this.el.setAttribute(name, value);
138
+ }
139
+ }
140
+ }
141
+
142
+ return AttrManager;
143
+
144
+ }));
@@ -0,0 +1,2 @@
1
+ /*! attr-manager 0.2.0 — © Christopher Torgalson */
2
+ class AttrManager{el;id;items=[];original=[];currentState=!1;restorers;static createId(){return Math.random().toString(36).slice(2,7)}constructor(t,e,r){this.el=t;let i=!1;this.id=AttrManager.createId();for(const[r,{whenTrue:s,whenFalse:a,initial:n,fixed:l}]of Object.entries(e)){if(void 0===s)throw new Error("AttrManager: each attribute must supply a `whenTrue` value.");if(void 0!==n&&!["whenTrue","whenFalse",null].includes(n))throw new Error("AttrManager: if attributes supply an `initial` value, it must be one of `whenTrue`, `whenFalse`, or `null`.");const e=t.getAttribute(r);this.original.push([r,e]);const o=void 0!==a?a:e;this.items.push({name:r,trueValue:s,falseValue:o,fixed:!!l}),void 0!==n&&(this.applyValue(r,"whenTrue"===n?s:o),i||(this.currentState="whenTrue"===n,i=!0))}r&&(this.restorers=r,r.push({id:this.id,restore:()=>this.restore()}))}toggle(t){this.currentState=t??!this.currentState;for(const{name:t,trueValue:e,falseValue:r,fixed:i}of this.items)i||this.applyValue(t,this.currentState?e:r)}restore(t=!1){for(const[t,e]of this.original)this.applyValue(t,e);t&&this.destroy()}destroy(){if(this.restorers){const t=this.restorers.findIndex(t=>t.id===this.id);t>-1&&this.restorers.splice(t,1)}this.items=[],this.original=[],this.currentState=!1}applyValue(t,e){this.el.getAttribute(t)!==e&&(null===e?this.el.removeAttribute(t):this.el.setAttribute(t,e))}}module.exports=AttrManager;
@@ -0,0 +1,2 @@
1
+ /*! attr-manager 0.2.0 — © Christopher Torgalson */
2
+ var global,factory;global=this,factory=function(){class AttrManager{el;id;items=[];original=[];currentState=!1;restorers;static createId(){return Math.random().toString(36).slice(2,7)}constructor(t,e,r){this.el=t;let i=!1;this.id=AttrManager.createId();for(const[r,{whenTrue:s,whenFalse:a,initial:o,fixed:n}]of Object.entries(e)){if(void 0===s)throw new Error("AttrManager: each attribute must supply a `whenTrue` value.");if(void 0!==o&&!["whenTrue","whenFalse",null].includes(o))throw new Error("AttrManager: if attributes supply an `initial` value, it must be one of `whenTrue`, `whenFalse`, or `null`.");const e=t.getAttribute(r);this.original.push([r,e]);const l=void 0!==a?a:e;this.items.push({name:r,trueValue:s,falseValue:l,fixed:!!n}),void 0!==o&&(this.applyValue(r,"whenTrue"===o?s:l),i||(this.currentState="whenTrue"===o,i=!0))}r&&(this.restorers=r,r.push({id:this.id,restore:()=>this.restore()}))}toggle(t){this.currentState=t??!this.currentState;for(const{name:t,trueValue:e,falseValue:r,fixed:i}of this.items)i||this.applyValue(t,this.currentState?e:r)}restore(t=!1){for(const[t,e]of this.original)this.applyValue(t,e);t&&this.destroy()}destroy(){if(this.restorers){const t=this.restorers.findIndex(t=>t.id===this.id);t>-1&&this.restorers.splice(t,1)}this.items=[],this.original=[],this.currentState=!1}applyValue(t,e){this.el.getAttribute(t)!==e&&(null===e?this.el.removeAttribute(t):this.el.setAttribute(t,e))}}return AttrManager},"object"==typeof exports&&"undefined"!=typeof module?module.exports=factory():"function"==typeof define&&define.amd?define(factory):(global="undefined"!=typeof globalThis?globalThis:global||self).AttrManager=factory();
@@ -0,0 +1,2 @@
1
+ /*! bh-attrmanager 0.0.0 — © Christopher Torgalson */
2
+ class BhAttrManager{el;id;items=[];original=[];currentState=!1;restorers;static createId(){return Math.random().toString(36).slice(2,7)}constructor(t,e,r){this.el=t;let i=!1;this.id=BhAttrManager.createId();for(const[r,{whenTrue:s,whenFalse:a,initial:n,fixed:h}]of Object.entries(e)){if(void 0===s)throw new Error("BhAttrManager: each attribute must supply a `whenTrue` value.");if(void 0!==n&&!["whenTrue","whenFalse",null].includes(n))throw new Error("BhAttrManager: if attributes supply an `initial` value, it must be one of `whenTrue`, `whenFalse`, or `null`.");const e=t.getAttribute(r);this.original.push([r,e]);const l=void 0!==a?a:e;this.items.push({name:r,trueValue:s,falseValue:l,fixed:!!h}),void 0!==n&&(this.applyValue(r,"whenTrue"===n?s:l),i||(this.currentState="whenTrue"===n,i=!0))}r&&(this.restorers=r,r.push({id:this.id,restore:()=>this.restore()}))}toggle(t){this.currentState=t??!this.currentState;for(const{name:t,trueValue:e,falseValue:r,fixed:i}of this.items)i||this.applyValue(t,this.currentState?e:r)}restore(t=!1){for(const[t,e]of this.original)this.applyValue(t,e);t&&this.destroy()}destroy(){if(this.restorers){const t=this.restorers.findIndex(t=>t.id===this.id);t>-1&&this.restorers.splice(t,1)}this.items=[],this.original=[],this.currentState=!1}applyValue(t,e){this.el.getAttribute(t)!==e&&(null===e?this.el.removeAttribute(t):this.el.setAttribute(t,e))}}module.exports=BhAttrManager;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * A type used to define possible values for BhAttrConfig's `initial` prop.
3
+ */
4
+ export type BhAttrInitialValue = "whenTrue" | "whenFalse" | null;
5
+ /**
6
+ * A type used to define the config option used by the constructor.
7
+ */
8
+ export type BhAttrConfig = Record<string, {
9
+ /** The value set for an attribute when currentState is `true`. */
10
+ whenTrue: string | null;
11
+ /** The value set for an attribute when currentState is `false`. */
12
+ whenFalse?: string | null;
13
+ /** The value set for an attribute in the constructor. */
14
+ initial?: BhAttrInitialValue;
15
+ /** Whether this attribute will be ignored by `.toggle()`. */
16
+ fixed?: boolean;
17
+ }>;
18
+ /**
19
+ * An internal type: guarantees `falseValue` is never undefined.
20
+ */
21
+ export interface BhNormalizedAttr {
22
+ /** The value set for an attribute when currentState is `true`. */
23
+ trueValue: string | null;
24
+ /** The value set for an attribute when currentState is `false`. */
25
+ falseValue: string | null;
26
+ /** The name of the attribute under management. */
27
+ name: string;
28
+ /** Whether this attribute will be ignored by `.toggle()`. */
29
+ fixed: boolean;
30
+ }
31
+ /**
32
+ * An entry in the `restorers` array.
33
+ */
34
+ export interface BhAttrRestorerEntry {
35
+ /** Unique ID for self-removal. */
36
+ id: string;
37
+ /** Restore method. */
38
+ restore: () => void;
39
+ }
40
+ /**
41
+ * A class used to create and/or enforce HTMLElement attribute values.
42
+ */
43
+ export default class BhAttrManager {
44
+ private readonly el;
45
+ /** Unique ID for self-removal from `restorers` array. */
46
+ private readonly id;
47
+ /** An array of the attributes under management in BhNormalizedAttr form. */
48
+ private items;
49
+ /** An array of the attribute values (used to restore initial DOM state). */
50
+ private original;
51
+ /** A var used to track the state of the attributes under management. */
52
+ private currentState;
53
+ /** Optional reference to the restorer array for self-removal. */
54
+ private readonly restorers?;
55
+ /**
56
+ * Generates a unique ID for this instance.
57
+ */
58
+ private static createId;
59
+ /**
60
+ * Constructs a new BhAttrManager instance.
61
+ *
62
+ * @param el
63
+ * The HTMLElement to manage.
64
+ * @param config
65
+ * The attribute configuration.
66
+ * @param restorers
67
+ * Optional restorer array for lifecycle management.
68
+ */
69
+ constructor(el: HTMLElement, config: BhAttrConfig, restorers?: BhAttrRestorerEntry[]);
70
+ /**
71
+ * Toggles state of attributes managed by this instance.
72
+ *
73
+ * @param condition
74
+ * The condition to set. If omitted, toggles the current state.
75
+ */
76
+ toggle(condition?: boolean): void;
77
+ /**
78
+ * Restores original state of attributes.
79
+ *
80
+ * @param teardown
81
+ * If `true` (default), also clears internal state and self-removes from
82
+ * `restorers`.
83
+ */
84
+ restore(teardown?: boolean): void;
85
+ /**
86
+ * Clears internal state and self-removes from `restorers`.
87
+ *
88
+ * Use this to clean up state without affecting the DOM.
89
+ */
90
+ destroy(): void;
91
+ /**
92
+ * Handles actual DOM attribute manipulation for toggle(), restore().
93
+ *
94
+ * @param name
95
+ * The attribute name.
96
+ * @param value
97
+ * The value to set. Pass `null` to remove the attribute.
98
+ */
99
+ private applyValue;
100
+ }
@@ -0,0 +1,2 @@
1
+ /*! bh-attrmanager 0.0.0 — © Christopher Torgalson */
2
+ class BhAttrManager{el;id;items=[];original=[];currentState=!1;restorers;static createId(){return Math.random().toString(36).slice(2,7)}constructor(t,e,r){this.el=t;let i=!1;this.id=BhAttrManager.createId();for(const[r,{whenTrue:s,whenFalse:a,initial:n,fixed:h}]of Object.entries(e)){if(void 0===s)throw new Error("BhAttrManager: each attribute must supply a `whenTrue` value.");if(void 0!==n&&!["whenTrue","whenFalse",null].includes(n))throw new Error("BhAttrManager: if attributes supply an `initial` value, it must be one of `whenTrue`, `whenFalse`, or `null`.");const e=t.getAttribute(r);this.original.push([r,e]);const l=void 0!==a?a:e;this.items.push({name:r,trueValue:s,falseValue:l,fixed:!!h}),void 0!==n&&(this.applyValue(r,"whenTrue"===n?s:l),i||(this.currentState="whenTrue"===n,i=!0))}r&&(this.restorers=r,r.push({id:this.id,restore:()=>this.restore()}))}toggle(t){this.currentState=t??!this.currentState;for(const{name:t,trueValue:e,falseValue:r,fixed:i}of this.items)i||this.applyValue(t,this.currentState?e:r)}restore(t=!1){for(const[t,e]of this.original)this.applyValue(t,e);t&&this.destroy()}destroy(){if(this.restorers){const t=this.restorers.findIndex(t=>t.id===this.id);t>-1&&this.restorers.splice(t,1)}this.items=[],this.original=[],this.currentState=!1}applyValue(t,e){this.el.getAttribute(t)!==e&&(null===e?this.el.removeAttribute(t):this.el.setAttribute(t,e))}}export{BhAttrManager as default};