@hortonstudio/main 1.9.10 → 1.9.20

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.
Files changed (124) hide show
  1. package/.prettierrc +8 -0
  2. package/README.md +146 -0
  3. package/eslint.config.js +32 -0
  4. package/index.ts +275 -0
  5. package/package.json +19 -2
  6. package/public/bootstrap.js +16 -0
  7. package/src/animations/animations.ts +93 -0
  8. package/src/animations/functions/counter/counter.ts +137 -0
  9. package/src/config.json +570 -0
  10. package/src/config.ts +105 -0
  11. package/src/modules/default/README.md +167 -0
  12. package/src/modules/default/default.ts +71 -0
  13. package/{autoInit → src/modules/default/functions}/accessibility/README.md +44 -12
  14. package/src/modules/default/functions/accessibility/accessibility.ts +54 -0
  15. package/src/modules/default/functions/accordion/README.md +451 -0
  16. package/src/modules/default/functions/accordion/accordion.ts +189 -0
  17. package/src/modules/default/functions/comparison/comparison.ts +424 -0
  18. package/src/modules/default/functions/marquee/marquee.ts +206 -0
  19. package/src/modules/default/functions/navbar/README.md +393 -0
  20. package/src/modules/default/functions/navbar/functions/arrow-navigation/arrow-navigation.ts +183 -0
  21. package/src/modules/default/functions/navbar/functions/dropdown/dropdown.ts +313 -0
  22. package/src/modules/default/functions/navbar/functions/menu/menu.ts +315 -0
  23. package/src/modules/default/functions/navbar/navbar.ts +51 -0
  24. package/{autoInit → src/modules/default/functions}/smooth-scroll/README.md +45 -14
  25. package/{autoInit/smooth-scroll/smooth-scroll.js → src/modules/default/functions/smooth-scroll/smooth-scroll.ts} +33 -38
  26. package/{autoInit → src/modules/default/functions}/transition/README.md +59 -32
  27. package/src/modules/default/functions/transition/transition.ts +290 -0
  28. package/src/modules/normalize/README.md +172 -0
  29. package/src/modules/normalize/functions/clickable/README.md +84 -0
  30. package/src/modules/normalize/functions/clickable/clickable.ts +43 -0
  31. package/src/modules/normalize/functions/clickable/functions/normalize/README.md +213 -0
  32. package/src/modules/normalize/functions/clickable/functions/normalize/normalize.ts +68 -0
  33. package/src/modules/normalize/functions/dupe/README.md +405 -0
  34. package/src/modules/normalize/functions/dupe/dupe.ts +197 -0
  35. package/src/modules/normalize/functions/sync/sync.ts +378 -0
  36. package/src/modules/normalize/normalize.ts +58 -0
  37. package/src/modules/structure/README.md +190 -0
  38. package/src/modules/structure/functions/form/README.md +94 -0
  39. package/src/modules/structure/functions/form/form.ts +54 -0
  40. package/src/modules/structure/functions/form/functions/honeypot/README.md +77 -0
  41. package/src/modules/structure/functions/form/functions/honeypot/honeypot.ts +37 -0
  42. package/src/modules/structure/functions/form/functions/range/README.md +410 -0
  43. package/src/modules/structure/functions/form/functions/range/range.ts +92 -0
  44. package/src/modules/structure/functions/form/functions/select/README.md +393 -0
  45. package/src/modules/structure/functions/form/functions/select/functions/custom-select/custom-select.ts +637 -0
  46. package/src/modules/structure/functions/form/functions/select/functions/states/states.ts +118 -0
  47. package/src/modules/structure/functions/form/functions/select/select.ts +48 -0
  48. package/src/modules/structure/functions/form/functions/test/test.ts +132 -0
  49. package/src/modules/structure/functions/pagination/README.md +527 -0
  50. package/src/modules/structure/functions/pagination/pagination.ts +493 -0
  51. package/src/modules/structure/functions/site-settings/README.md +395 -0
  52. package/src/modules/structure/functions/site-settings/site-settings.ts +158 -0
  53. package/{autoInit/accessibility → src/modules/structure}/functions/toc/README.md +18 -15
  54. package/{autoInit/accessibility/functions/toc/toc.js → src/modules/structure/functions/toc/functions/heading-links/heading-links.ts} +43 -63
  55. package/src/modules/structure/functions/toc/functions/progress-bar/progress-bar.ts +101 -0
  56. package/src/modules/structure/functions/toc/toc.ts +35 -0
  57. package/{autoInit/accessibility → src/modules/structure}/functions/year-replacement/README.md +7 -6
  58. package/src/modules/structure/functions/year-replacement/year-replacement.ts +59 -0
  59. package/src/modules/structure/structure.ts +59 -0
  60. package/src/utils/attributeSelector.ts +78 -0
  61. package/src/utils/cssVariables.ts +24 -0
  62. package/src/utils/gsap.ts +198 -0
  63. package/src/utils/heightAnimator.ts +130 -0
  64. package/src/utils/modalManager.ts +150 -0
  65. package/src/utils.ts +54 -0
  66. package/tsconfig.json +24 -0
  67. package/vite.config.js +45 -0
  68. package/.claude/settings.local.json +0 -70
  69. package/archive/hero.js +0 -794
  70. package/archive/modal.js +0 -80
  71. package/archive/text.js +0 -628
  72. package/autoInit/accessibility/accessibility.js +0 -53
  73. package/autoInit/accessibility/functions/blog-remover/README.md +0 -61
  74. package/autoInit/accessibility/functions/blog-remover/blog-remover.js +0 -31
  75. package/autoInit/accessibility/functions/click-forwarding/README.md +0 -60
  76. package/autoInit/accessibility/functions/click-forwarding/click-forwarding.js +0 -82
  77. package/autoInit/accessibility/functions/dropdown/README.md +0 -212
  78. package/autoInit/accessibility/functions/dropdown/dropdown.js +0 -167
  79. package/autoInit/accessibility/functions/list-accessibility/README.md +0 -56
  80. package/autoInit/accessibility/functions/list-accessibility/list-accessibility.js +0 -23
  81. package/autoInit/accessibility/functions/pagination/README.md +0 -428
  82. package/autoInit/accessibility/functions/pagination/pagination.js +0 -359
  83. package/autoInit/accessibility/functions/text-synchronization/README.md +0 -62
  84. package/autoInit/accessibility/functions/text-synchronization/text-synchronization.js +0 -101
  85. package/autoInit/accessibility/functions/year-replacement/year-replacement.js +0 -43
  86. package/autoInit/button/README.md +0 -122
  87. package/autoInit/button/button.js +0 -51
  88. package/autoInit/counter/README.md +0 -274
  89. package/autoInit/counter/counter.js +0 -185
  90. package/autoInit/form/README.md +0 -338
  91. package/autoInit/form/form.js +0 -374
  92. package/autoInit/navbar/README.md +0 -366
  93. package/autoInit/navbar/navbar.js +0 -786
  94. package/autoInit/site-settings/README.md +0 -218
  95. package/autoInit/site-settings/site-settings.js +0 -134
  96. package/autoInit/transition/transition.js +0 -116
  97. package/index.js +0 -305
  98. package/utils/before-after/README.md +0 -520
  99. package/utils/before-after/before-after.js +0 -653
  100. package/utils/css-animations/buttons/main/bgbasic/btn-main-bgbasic.html +0 -10
  101. package/utils/css-animations/buttons/main/bgfill/btn-main-bgfill.html +0 -29
  102. package/utils/css-animations/buttons/navbar/bgbasic/navbar-main-bgbasic.html +0 -17
  103. package/utils/css-animations/buttons/navbar/bgbasic/navbar-menu-bgbasic.html +0 -16
  104. package/utils/css-animations/buttons/navbar/bgfill/navbar-main-bgfill.html +0 -46
  105. package/utils/css-animations/buttons/navbar/bgfill/navbar-menu-bgfill.html +0 -39
  106. package/utils/css-animations/buttons/navbar/color/navbar-announce-color.html +0 -5
  107. package/utils/css-animations/buttons/navbar/color/navbar-main-color.html +0 -7
  108. package/utils/css-animations/buttons/navbar/color/navbar-menu-color.html +0 -7
  109. package/utils/css-animations/buttons/navbar/double-slide/navbar-announce-double-slide.html +0 -40
  110. package/utils/css-animations/buttons/navbar/double-slide/navbar-main-double-slide.html +0 -77
  111. package/utils/css-animations/buttons/navbar/scale/navbar-announce-scale.html +0 -6
  112. package/utils/css-animations/buttons/navbar/scale/navbar-main-scale.html +0 -9
  113. package/utils/css-animations/buttons/navbar/scale/navbar-menu-scale.html +0 -8
  114. package/utils/css-animations/buttons/navbar/underline/navbar-announce-underline.html +0 -32
  115. package/utils/css-animations/buttons/navbar/underline/navbar-main-underline.html +0 -56
  116. package/utils/css-animations/buttons/text/color/text-footer-color.html +0 -5
  117. package/utils/css-animations/buttons/text/color/text-main-color.html +0 -5
  118. package/utils/css-animations/buttons/text/double-slide/text-main-double-slide.html +0 -56
  119. package/utils/css-animations/buttons/text/scale/text-footer-scale.html +0 -6
  120. package/utils/css-animations/buttons/text/scale/text-main-scale.html +0 -6
  121. package/utils/css-animations/buttons/text/underline/text-footer-underline.html +0 -45
  122. package/utils/css-animations/buttons/text/underline/text-main-underline.html +0 -58
  123. package/utils/css-animations/cards/card-clickable.html +0 -11
  124. package/utils/css-animations/defaults.html +0 -69
@@ -0,0 +1,118 @@
1
+ import { querySelectorAll } from '@utils';
2
+
3
+ const US_STATES = [
4
+ { name: 'Alabama', value: 'AL' },
5
+ { name: 'Alaska', value: 'AK' },
6
+ { name: 'Arizona', value: 'AZ' },
7
+ { name: 'Arkansas', value: 'AR' },
8
+ { name: 'California', value: 'CA' },
9
+ { name: 'Colorado', value: 'CO' },
10
+ { name: 'Connecticut', value: 'CT' },
11
+ { name: 'Delaware', value: 'DE' },
12
+ { name: 'Florida', value: 'FL' },
13
+ { name: 'Georgia', value: 'GA' },
14
+ { name: 'Hawaii', value: 'HI' },
15
+ { name: 'Idaho', value: 'ID' },
16
+ { name: 'Illinois', value: 'IL' },
17
+ { name: 'Indiana', value: 'IN' },
18
+ { name: 'Iowa', value: 'IA' },
19
+ { name: 'Kansas', value: 'KS' },
20
+ { name: 'Kentucky', value: 'KY' },
21
+ { name: 'Louisiana', value: 'LA' },
22
+ { name: 'Maine', value: 'ME' },
23
+ { name: 'Maryland', value: 'MD' },
24
+ { name: 'Massachusetts', value: 'MA' },
25
+ { name: 'Michigan', value: 'MI' },
26
+ { name: 'Minnesota', value: 'MN' },
27
+ { name: 'Mississippi', value: 'MS' },
28
+ { name: 'Missouri', value: 'MO' },
29
+ { name: 'Montana', value: 'MT' },
30
+ { name: 'Nebraska', value: 'NE' },
31
+ { name: 'Nevada', value: 'NV' },
32
+ { name: 'New Hampshire', value: 'NH' },
33
+ { name: 'New Jersey', value: 'NJ' },
34
+ { name: 'New Mexico', value: 'NM' },
35
+ { name: 'New York', value: 'NY' },
36
+ { name: 'North Carolina', value: 'NC' },
37
+ { name: 'North Dakota', value: 'ND' },
38
+ { name: 'Ohio', value: 'OH' },
39
+ { name: 'Oklahoma', value: 'OK' },
40
+ { name: 'Oregon', value: 'OR' },
41
+ { name: 'Pennsylvania', value: 'PA' },
42
+ { name: 'Rhode Island', value: 'RI' },
43
+ { name: 'South Carolina', value: 'SC' },
44
+ { name: 'South Dakota', value: 'SD' },
45
+ { name: 'Tennessee', value: 'TN' },
46
+ { name: 'Texas', value: 'TX' },
47
+ { name: 'Utah', value: 'UT' },
48
+ { name: 'Vermont', value: 'VT' },
49
+ { name: 'Virginia', value: 'VA' },
50
+ { name: 'Washington', value: 'WA' },
51
+ { name: 'West Virginia', value: 'WV' },
52
+ { name: 'Wisconsin', value: 'WI' },
53
+ { name: 'Wyoming', value: 'WY' },
54
+ ];
55
+
56
+ export function init(config) {
57
+ // Find all select elements with data-hs-form-select="states"
58
+ const stateSelects = querySelectorAll(config, 'states');
59
+
60
+ stateSelects.forEach((select) => {
61
+ if (select.tagName !== 'SELECT') {
62
+ console.warn(
63
+ '[select-states] data-hs-form-select="states" must be on a <select> element',
64
+ select
65
+ );
66
+ return;
67
+ }
68
+
69
+ const existingOptions = select.querySelectorAll('option');
70
+
71
+ // Validate: Must have exactly 1 option (placeholder template)
72
+ if (existingOptions.length !== 1) {
73
+ console.warn(
74
+ '[select-states] Select must have exactly 1 default template option (placeholder). Found:',
75
+ existingOptions.length,
76
+ select
77
+ );
78
+ return;
79
+ }
80
+
81
+ const templateOption = existingOptions[0];
82
+
83
+ // Validate: Template option must have empty value
84
+ if (templateOption.value !== '') {
85
+ console.warn(
86
+ '[select-states] Template option must have empty value for placeholder. Found value:',
87
+ templateOption.value,
88
+ select
89
+ );
90
+ return;
91
+ }
92
+
93
+ // Store placeholder text and clear select
94
+ const placeholderText = templateOption.textContent;
95
+ select.innerHTML = '';
96
+
97
+ // Re-create placeholder as first option
98
+ const placeholder = document.createElement('option');
99
+ placeholder.value = '';
100
+ placeholder.textContent = placeholderText;
101
+ select.appendChild(placeholder);
102
+
103
+ // Add all 50 states after placeholder
104
+ US_STATES.forEach((state) => {
105
+ const option = document.createElement('option');
106
+ option.value = state.value;
107
+ option.textContent = state.name;
108
+ select.appendChild(option);
109
+ });
110
+ });
111
+
112
+ return {
113
+ result: `states initialized on ${stateSelects.length} select${stateSelects.length !== 1 ? 's' : ''}`,
114
+ destroy: () => {
115
+ // No cleanup needed - states are just populated into native select
116
+ },
117
+ };
118
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Select Orchestrator
3
+ * Manages select enhancement functions in sequence
4
+ *
5
+ * Uses static imports and passes config down to functions
6
+ * @version 2.0.0
7
+ */
8
+ import { init as statesInit } from './functions/states/states.ts';
9
+ import { init as customSelectInit } from './functions/custom-select/custom-select.ts';
10
+
11
+ export async function init(selectConfig) {
12
+ const cleanup = { destroyFunctions: [] };
13
+
14
+ try {
15
+ // IMPORTANT: Load states FIRST to populate native select,
16
+ // then load custom-select to create custom UI
17
+ const statesResult = await statesInit(selectConfig.states);
18
+ if (statesResult?.destroy) cleanup.destroyFunctions.push(statesResult.destroy);
19
+
20
+ const customSelectResult = await customSelectInit(selectConfig['custom-select']);
21
+ if (customSelectResult?.destroy) cleanup.destroyFunctions.push(customSelectResult.destroy);
22
+
23
+ return {
24
+ result: 'select initialized',
25
+ destroy: () => {
26
+ cleanup.destroyFunctions.forEach((destroyFn) => {
27
+ try {
28
+ destroyFn();
29
+ } catch (error) {
30
+ console.error('[select] Error during cleanup:', error);
31
+ }
32
+ });
33
+ cleanup.destroyFunctions.length = 0;
34
+ },
35
+ };
36
+ } catch (error) {
37
+ console.error('[select] Initialization failed:', error);
38
+ // Cleanup any partial initialization
39
+ cleanup.destroyFunctions.forEach((fn) => {
40
+ try {
41
+ fn();
42
+ } catch (cleanupError) {
43
+ console.error('[select] Error during error cleanup:', cleanupError);
44
+ }
45
+ });
46
+ throw error;
47
+ }
48
+ }
@@ -0,0 +1,132 @@
1
+ import { querySelectorAll, querySelector } from '@utils';
2
+
3
+ export function init(config) {
4
+ // Centralized cleanup tracking
5
+ const cleanup = {
6
+ handlers: [],
7
+ };
8
+
9
+ const addHandler = (element, event, handler, options) => {
10
+ element.addEventListener(event, handler, options);
11
+ cleanup.handlers.push({ element, event, handler, options });
12
+ };
13
+
14
+ // Find all test wrappers
15
+ const testWrappers = querySelectorAll(config, 'wrapper');
16
+
17
+ testWrappers.forEach((wrapper) => {
18
+ // Find form element within wrapper
19
+ const form = wrapper.querySelector('form');
20
+ if (!form) {
21
+ console.warn(
22
+ '[form-test] No <form> element found within data-hs-form-test="wrapper"',
23
+ wrapper
24
+ );
25
+ return;
26
+ }
27
+
28
+ // Find test info element (optional)
29
+ const testInfo = querySelector(config, 'info', wrapper);
30
+
31
+ // Function to collect and display current form data
32
+ const updateLiveData = () => {
33
+ const formData = new FormData(form);
34
+ const data = {};
35
+ for (const [key, value] of formData.entries()) {
36
+ data[key] = value;
37
+ }
38
+
39
+ if (testInfo) {
40
+ // Show live form data
41
+ const liveDisplay = document.createElement('pre');
42
+ liveDisplay.textContent = JSON.stringify(data, null, 2);
43
+
44
+ testInfo.innerHTML = '';
45
+ testInfo.appendChild(document.createTextNode('Test mode active - Live form data:'));
46
+ testInfo.appendChild(liveDisplay);
47
+ }
48
+ };
49
+
50
+ // Set initial message and data
51
+ if (testInfo) {
52
+ testInfo.textContent = 'Test mode active, preventing native submissions';
53
+ // Show initial form state
54
+ updateLiveData();
55
+ }
56
+
57
+ // Listen to all form inputs for live updates
58
+ addHandler(form, 'input', updateLiveData);
59
+ addHandler(form, 'change', updateLiveData);
60
+
61
+ // Find submit button
62
+ const submitButton =
63
+ form.querySelector('button[type="submit"], input[type="submit"]') ||
64
+ form.querySelector('button:not([type])');
65
+
66
+ // Track button clicks to detect when browser validation blocks submission
67
+ if (submitButton) {
68
+ const clickHandler = () => {
69
+ console.log('[form-test] Submit button clicked');
70
+
71
+ // Use requestAnimationFrame to check if form will submit
72
+ // If form is invalid, submit event won't fire
73
+ requestAnimationFrame(() => {
74
+ if (!form.checkValidity()) {
75
+ console.log('[form-test] Browser blocked submission - validation failed');
76
+ }
77
+ });
78
+ };
79
+ addHandler(submitButton, 'click', clickHandler);
80
+ }
81
+
82
+ // Handle form submission
83
+ const submitHandler = (e) => {
84
+ e.preventDefault(); // Prevent actual submission
85
+ e.stopPropagation(); // Stop event from bubbling
86
+ e.stopImmediatePropagation(); // Stop other listeners on same element
87
+
88
+ console.log('[form-test] Submission prevented - displaying test results');
89
+
90
+ // Get form data
91
+ const formData = new FormData(form);
92
+ const data = {};
93
+ for (const [key, value] of formData.entries()) {
94
+ data[key] = value;
95
+ }
96
+
97
+ // Create success message
98
+ const timestamp = new Date().toLocaleTimeString();
99
+ const message = `✅ Form would submit successfully at ${timestamp}`;
100
+
101
+ // Display in test info element or console
102
+ if (testInfo) {
103
+ // Show form data in a formatted way
104
+ const dataDisplay = document.createElement('pre');
105
+ dataDisplay.textContent = JSON.stringify(data, null, 2);
106
+
107
+ testInfo.innerHTML = ''; // Clear previous
108
+ testInfo.appendChild(document.createTextNode(message));
109
+ testInfo.appendChild(dataDisplay);
110
+ } else {
111
+ console.log(message);
112
+ console.log('Form data:', data);
113
+ }
114
+
115
+ return false; // Extra insurance to prevent submission
116
+ };
117
+
118
+ // Use capture phase to catch submit event before anything else
119
+ addHandler(form, 'submit', submitHandler, true);
120
+ });
121
+
122
+ return {
123
+ result: `test initialized on ${testWrappers.length} form${testWrappers.length !== 1 ? 's' : ''}`,
124
+ destroy: () => {
125
+ // Remove all event listeners
126
+ cleanup.handlers.forEach(({ element, event, handler, options }) => {
127
+ element.removeEventListener(event, handler, options);
128
+ });
129
+ cleanup.handlers.length = 0;
130
+ },
131
+ };
132
+ }