create-wp-typia 0.1.0 → 1.0.1

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 (91) hide show
  1. package/README.md +8 -28
  2. package/bin/create-wp-typia.js +3 -0
  3. package/package.json +9 -37
  4. package/dist/cli.js +0 -87837
  5. package/dist/highlights-eq9cgrbb.scm +0 -604
  6. package/dist/highlights-ghv9g403.scm +0 -205
  7. package/dist/highlights-hk7bwhj4.scm +0 -284
  8. package/dist/highlights-r812a2qc.scm +0 -150
  9. package/dist/highlights-x6tmsnaa.scm +0 -115
  10. package/dist/injections-73j83es3.scm +0 -27
  11. package/dist/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
  12. package/dist/tree-sitter-markdown-411r6y9b.wasm +0 -0
  13. package/dist/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
  14. package/dist/tree-sitter-typescript-zxjzwt75.wasm +0 -0
  15. package/dist/tree-sitter-zig-e78zbjpm.wasm +0 -0
  16. package/lib/entry.js +0 -29
  17. package/lib/node-cli.js +0 -326
  18. package/lib/package-managers.d.ts +0 -29
  19. package/lib/package-managers.js +0 -170
  20. package/lib/scaffold.d.ts +0 -64
  21. package/lib/scaffold.js +0 -565
  22. package/lib/template-registry.d.ts +0 -18
  23. package/lib/template-registry.js +0 -58
  24. package/src/cli.ts +0 -329
  25. package/templates/advanced/README.md.mustache +0 -70
  26. package/templates/advanced/block.json.mustache +0 -42
  27. package/templates/advanced/index.js +0 -21
  28. package/templates/advanced/package.json.mustache +0 -48
  29. package/templates/advanced/scripts/generate-migrations.ts.mustache +0 -267
  30. package/templates/advanced/scripts/lib/typia-metadata-core.ts +0 -806
  31. package/templates/advanced/scripts/migration-cli.ts.mustache +0 -260
  32. package/templates/advanced/scripts/sync-types-to-block-json.ts.mustache +0 -25
  33. package/templates/advanced/src/admin/migration-dashboard.tsx.mustache +0 -450
  34. package/templates/advanced/src/components/ErrorBoundary.tsx.mustache +0 -47
  35. package/templates/advanced/src/deprecated.ts.mustache +0 -184
  36. package/templates/advanced/src/edit.tsx.mustache +0 -93
  37. package/templates/advanced/src/hooks/useDebounce.ts.mustache +0 -20
  38. package/templates/advanced/src/hooks/useLocalStorage.ts.mustache +0 -31
  39. package/templates/advanced/src/hooks.ts.mustache +0 -56
  40. package/templates/advanced/src/index.tsx.mustache +0 -16
  41. package/templates/advanced/src/migration-detector.ts.mustache +0 -417
  42. package/templates/advanced/src/migrations/index.ts.mustache +0 -361
  43. package/templates/advanced/src/save.tsx.mustache +0 -40
  44. package/templates/advanced/src/style.scss.mustache +0 -84
  45. package/templates/advanced/src/types/versions.ts.mustache +0 -108
  46. package/templates/advanced/src/types.ts.mustache +0 -45
  47. package/templates/advanced/src/utils/classnames.ts.mustache +0 -51
  48. package/templates/advanced/src/utils/debounce.ts.mustache +0 -37
  49. package/templates/advanced/src/utils/index.ts.mustache +0 -7
  50. package/templates/advanced/src/utils/uuid.ts.mustache +0 -17
  51. package/templates/advanced/src/validators.ts.mustache +0 -39
  52. package/templates/advanced/src/view.ts.mustache +0 -59
  53. package/templates/advanced/tsconfig.json.mustache +0 -9
  54. package/templates/advanced/webpack.config.js.mustache +0 -85
  55. package/templates/basic/package.json.mustache +0 -39
  56. package/templates/basic/scripts/lib/typia-metadata-core.ts +0 -806
  57. package/templates/basic/scripts/sync-types-to-block-json.ts +0 -25
  58. package/templates/basic/src/block.json +0 -51
  59. package/templates/basic/src/edit.tsx +0 -85
  60. package/templates/basic/src/hooks.ts +0 -75
  61. package/templates/basic/src/index.tsx +0 -37
  62. package/templates/basic/src/save.tsx +0 -27
  63. package/templates/basic/src/style.scss +0 -42
  64. package/templates/basic/src/types.ts +0 -47
  65. package/templates/basic/src/validators.ts +0 -39
  66. package/templates/basic/tsconfig.json +0 -20
  67. package/templates/basic/webpack.config.js +0 -85
  68. package/templates/full/package.json.mustache +0 -40
  69. package/templates/full/scripts/lib/typia-metadata-core.ts +0 -806
  70. package/templates/full/scripts/sync-types-to-block-json.ts.mustache +0 -25
  71. package/templates/full/src/block.json.mustache +0 -121
  72. package/templates/full/src/edit.tsx.mustache +0 -300
  73. package/templates/full/src/editor.scss.mustache +0 -251
  74. package/templates/full/src/hooks.ts.mustache +0 -140
  75. package/templates/full/src/index.tsx.mustache +0 -27
  76. package/templates/full/src/save.tsx.mustache +0 -39
  77. package/templates/full/src/style.scss.mustache +0 -224
  78. package/templates/full/src/types.ts.mustache +0 -34
  79. package/templates/full/src/validators.ts.mustache +0 -84
  80. package/templates/full/tsconfig.json.mustache +0 -9
  81. package/templates/full/webpack.config.js.mustache +0 -85
  82. package/templates/interactivity/package.json.mustache +0 -41
  83. package/templates/interactivity/scripts/lib/typia-metadata-core.ts +0 -806
  84. package/templates/interactivity/scripts/sync-types-to-block-json.ts.mustache +0 -25
  85. package/templates/interactivity/src/block.json.mustache +0 -75
  86. package/templates/interactivity/src/edit.tsx.mustache +0 -206
  87. package/templates/interactivity/src/interactivity.ts.mustache +0 -183
  88. package/templates/interactivity/src/save.tsx.mustache +0 -87
  89. package/templates/interactivity/src/types.ts.mustache +0 -29
  90. package/templates/interactivity/tsconfig.json.mustache +0 -9
  91. package/templates/interactivity/webpack.config.js.mustache +0 -85
@@ -1,25 +0,0 @@
1
- import { syncBlockMetadata } from "./lib/typia-metadata-core";
2
-
3
- async function main() {
4
- const result = await syncBlockMetadata({
5
- blockJsonFile: "src/block.json",
6
- manifestFile: "src/typia.manifest.json",
7
- sourceTypeName: "{{pascalCase}}Attributes",
8
- typesFile: "src/types.ts",
9
- });
10
-
11
- console.log("✅ block.json and typia.manifest.json were generated from TypeScript types!");
12
- console.log("📝 Generated attributes:", result.attributeNames);
13
-
14
- if (result.lossyProjectionWarnings.length > 0) {
15
- console.warn("⚠️ Some Typia constraints were preserved only in typia.manifest.json:");
16
- for (const warning of result.lossyProjectionWarnings) {
17
- console.warn(` - ${warning}`);
18
- }
19
- }
20
- }
21
-
22
- main().catch((error) => {
23
- console.error("❌ Type sync failed:", error);
24
- process.exit(1);
25
- });
@@ -1,75 +0,0 @@
1
- {
2
- "$schema": "https://schemas.wp.org/trunk/block.json",
3
- "apiVersion": 3,
4
- "name": "create-block/{{slugKebabCase}}",
5
- "version": "0.1.0",
6
- "title": "{{title}}",
7
- "category": "widgets",
8
- "icon": "smiley",
9
- "description": "{{description}}",
10
- "example": {},
11
- "supports": {
12
- "html": false,
13
- "align": true,
14
- "anchor": true,
15
- "className": true,
16
- "interactivity": true
17
- },
18
- "attributes": {
19
- "content": {
20
- "type": "string",
21
- "source": "html",
22
- "selector": ".{{cssClassName}}__content",
23
- "default": ""
24
- },
25
- "alignment": {
26
- "type": "string",
27
- "enum": ["left", "center", "right"],
28
- "default": "left"
29
- },
30
- "isVisible": {
31
- "type": "boolean",
32
- "default": true
33
- },
34
- "interactiveMode": {
35
- "type": "string",
36
- "enum": ["click", "hover", "auto"],
37
- "default": "click"
38
- },
39
- "animation": {
40
- "type": "string",
41
- "enum": ["none", "bounce", "pulse", "shake", "flip"],
42
- "default": "none"
43
- },
44
- "clickCount": {
45
- "type": "number",
46
- "default": 0
47
- },
48
- "isAnimating": {
49
- "type": "boolean",
50
- "default": false
51
- },
52
- "showCounter": {
53
- "type": "boolean",
54
- "default": true
55
- },
56
- "maxClicks": {
57
- "type": "number",
58
- "default": 10
59
- },
60
- "autoPlayInterval": {
61
- "type": "number",
62
- "default": 0
63
- },
64
- "uniqueId": {
65
- "type": "string",
66
- "default": ""
67
- }
68
- },
69
- "textdomain": "{{slugSnakeCase}}",
70
- "editorScript": "file:./index.js",
71
- "editorStyle": "file:./index.css",
72
- "style": "file:./style-index.css",
73
- "viewScript": "file:./view.js",
74
- "viewScriptModule": "file:./interactivity.js"
75
- }
@@ -1,206 +0,0 @@
1
- import { __ } from '@wordpress/i18n';
2
- import { useBlockProps, InspectorControls, RichText, BlockControls, AlignmentToolbar } from '@wordpress/block-editor';
3
- import { PanelBody, ToggleControl, SelectControl, RangeControl, TextControl, Button, Notice } from '@wordpress/components';
4
- import { useState, useEffect } from '@wordpress/element';
5
- import type { {{pascalCase}}Attributes } from './types';
6
-
7
- export default function Edit({ attributes, setAttributes, isSelected }: {
8
- attributes: {{pascalCase}}Attributes;
9
- setAttributes: (attrs: Partial<{{pascalCase}}Attributes>) => void;
10
- isSelected: boolean;
11
- }) {
12
- const [isPreviewing, setIsPreviewing] = useState(false);
13
-
14
- const blockProps = useBlockProps({
15
- className: `wp-block-{{slugKebabCase}} wp-block-{{slugKebabCase}}--${attributes.interactiveMode}`,
16
- 'data-wp-interactive': '{{slugKebabCase}}',
17
- 'data-wp-context': JSON.stringify({
18
- clicks: attributes.clickCount,
19
- isAnimating: attributes.isAnimating,
20
- isVisible: attributes.isVisible,
21
- lastInteraction: '',
22
- animation: attributes.animation,
23
- interactiveMode: attributes.interactiveMode,
24
- maxClicks: attributes.maxClicks,
25
- autoPlayInterval: attributes.autoPlayInterval
26
- })
27
- });
28
-
29
- const resetCounter = () => {
30
- setAttributes({ clickCount: 0, isAnimating: false });
31
- };
32
-
33
- const testAnimation = () => {
34
- setAttributes({ isAnimating: true });
35
- setTimeout(() => {
36
- setAttributes({ isAnimating: false });
37
- }, 1000);
38
- };
39
-
40
- return (
41
- <>
42
- <BlockControls>
43
- <AlignmentToolbar
44
- value={attributes.alignment}
45
- onChange={(value) => setAttributes({ alignment: value || 'left' })}
46
- />
47
- </BlockControls>
48
-
49
- <InspectorControls>
50
- <PanelBody title={__('Interactive Settings', '{{slugSnakeCase}}')}>
51
- <SelectControl
52
- label={__('Interactive Mode', '{{slugSnakeCase}}')}
53
- value={attributes.interactiveMode}
54
- options={[
55
- { label: __('Click', '{{slugSnakeCase}}'), value: 'click' },
56
- { label: __('Hover', '{{slugSnakeCase}}'), value: 'hover' },
57
- { label: __('Auto Play', '{{slugSnakeCase}}'), value: 'auto' }
58
- ]}
59
- onChange={(value) => setAttributes({ interactiveMode: value })}
60
- />
61
-
62
- <SelectControl
63
- label={__('Animation', '{{slugSnakeCase}}')}
64
- value={attributes.animation}
65
- options={[
66
- { label: __('None', '{{slugSnakeCase}}'), value: 'none' },
67
- { label: __('Bounce', '{{slugSnakeCase}}'), value: 'bounce' },
68
- { label: __('Pulse', '{{slugSnakeCase}}'), value: 'pulse' },
69
- { label: __('Shake', '{{slugSnakeCase}}'), value: 'shake' },
70
- { label: __('Flip', '{{slugSnakeCase}}'), value: 'flip' }
71
- ]}
72
- onChange={(value) => setAttributes({ animation: value })}
73
- />
74
-
75
- <ToggleControl
76
- label={__('Show Counter', '{{slugSnakeCase}}')}
77
- checked={attributes.showCounter}
78
- onChange={(value) => setAttributes({ showCounter: value })}
79
- />
80
-
81
- <ToggleControl
82
- label={__('Visible', '{{slugSnakeCase}}')}
83
- checked={attributes.isVisible}
84
- onChange={(value) => setAttributes({ isVisible: value })}
85
- />
86
- </PanelBody>
87
-
88
- <PanelBody title={__('Counter Settings', '{{slugSnakeCase}}')}>
89
- <RangeControl
90
- label={__('Max Clicks', '{{slugSnakeCase}}')}
91
- value={attributes.maxClicks}
92
- onChange={(value) => setAttributes({ maxClicks: value })}
93
- min={0}
94
- max={100}
95
- help={__('Set to 0 for unlimited clicks', '{{slugSnakeCase}}')}
96
- />
97
-
98
- {attributes.interactiveMode === 'auto' && (
99
- <RangeControl
100
- label={__('Auto Play Interval (ms)', '{{slugSnakeCase}}')}
101
- value={attributes.autoPlayInterval}
102
- onChange={(value) => setAttributes({ autoPlayInterval: value })}
103
- min={100}
104
- max={5000}
105
- step={100}
106
- help={__('Interval between automatic animations', '{{slugSnakeCase}}')}
107
- />
108
- )}
109
-
110
- <div style={{ display: 'flex', gap: '8px', marginTop: '16px' }}>
111
- <Button
112
- variant="secondary"
113
- onClick={resetCounter}
114
- isSmall
115
- >
116
- {__('Reset Counter', '{{slugSnakeCase}}')}
117
- </Button>
118
- <Button
119
- variant="secondary"
120
- onClick={testAnimation}
121
- isSmall
122
- >
123
- {__('Test Animation', '{{slugSnakeCase}}')}
124
- </Button>
125
- </div>
126
-
127
- <TextControl
128
- label={__('Unique ID', '{{slugSnakeCase}}')}
129
- value={attributes.uniqueId}
130
- onChange={(value) => setAttributes({ uniqueId: value })}
131
- help={__('Optional unique identifier for this block instance', '{{slugSnakeCase}}')}
132
- />
133
- </PanelBody>
134
-
135
- {isSelected && (
136
- <PanelBody title={__('Preview', '{{slugSnakeCase}}')}>
137
- <ToggleControl
138
- label={__('Enable Preview Mode', '{{slugSnakeCase}}')}
139
- checked={isPreviewing}
140
- onChange={setIsPreviewing}
141
- help={__('Test interactions in the editor', '{{slugSnakeCase}}')}
142
- />
143
-
144
- {attributes.clickCount > 0 && (
145
- <Notice status="info" isDismissible={false}>
146
- {__('Current clicks:', '{{slugSnakeCase}}')} {attributes.clickCount}
147
- {attributes.maxClicks > 0 && ` / ${attributes.maxClicks}`}
148
- </Notice>
149
- )}
150
- </PanelBody>
151
- )}
152
- </InspectorControls>
153
-
154
- <div {...blockProps}>
155
- <div
156
- className={`{{cssClassName}}__content ${attributes.isAnimating ? 'is-animating' : ''}`}
157
- style={{ textAlign: attributes.alignment }}
158
- data-wp-on--click={isPreviewing ? 'actions.handleClick' : undefined}
159
- data-wp-on--mouseenter={isPreviewing && attributes.interactiveMode === 'hover' ? 'actions.handleMouseEnter' : undefined}
160
- data-wp-on--mouseleave={isPreviewing && attributes.interactiveMode === 'hover' ? 'actions.handleMouseLeave' : undefined}
161
- >
162
- <RichText
163
- tagName="p"
164
- value={attributes.content}
165
- onChange={(value) => setAttributes({ content: value })}
166
- placeholder={__('{{title}} – click me to interact!', '{{slugSnakeCase}}')}
167
- withoutInteractiveFormatting
168
- />
169
-
170
- {attributes.showCounter && (
171
- <div className="{{cssClassName}}__counter">
172
- <span className="{{cssClassName}}__counter-label">
173
- {__('Clicks:', '{{slugSnakeCase}}')}
174
- </span>
175
- <span
176
- className="{{cssClassName}}__counter-value"
177
- data-wp-text="state.clicks"
178
- >
179
- {attributes.clickCount}
180
- </span>
181
- </div>
182
- )}
183
-
184
- {attributes.maxClicks > 0 && (
185
- <div className="{{cssClassName}}__progress">
186
- <div
187
- className="{{cssClassName}}__progress-bar"
188
- style={{ width: `${(attributes.clickCount / attributes.maxClicks) * 100}%` }}
189
- data-wp-style--width="state.progress + '%'"
190
- />
191
- </div>
192
- )}
193
-
194
- {attributes.animation !== 'none' && (
195
- <div
196
- className={`{{cssClassName}}__animation ${attributes.isAnimating ? 'is-active' : ''}`}
197
- data-wp-class="is-active"
198
- >
199
- {attributes.animation}
200
- </div>
201
- )}
202
- </div>
203
- </div>
204
- </>
205
- );
206
- }
@@ -1,183 +0,0 @@
1
- /**
2
- * WordPress Interactivity API implementation for {{title}} block
3
- */
4
- import { store, getContext, getElement } from '@wordpress/interactivity';
5
-
6
- // Store configuration
7
- store('{{slugKebabCase}}', {
8
- // State - reactive data that updates the UI
9
- state: {
10
- get clicks() {
11
- return getContext().clicks;
12
- },
13
- get isAnimating() {
14
- return getContext().isAnimating;
15
- },
16
- get isVisible() {
17
- return getContext().isVisible;
18
- },
19
- get animationClass() {
20
- const context = getContext();
21
- if (!context.isAnimating) return '';
22
-
23
- switch (context.animation) {
24
- case 'bounce':
25
- return 'animate-bounce';
26
- case 'pulse':
27
- return 'animate-pulse';
28
- case 'shake':
29
- return 'animate-shake';
30
- case 'flip':
31
- return 'animate-flip';
32
- default:
33
- return '';
34
- }
35
- },
36
- get progress() {
37
- const context = getContext();
38
- return context.maxClicks > 0 ? (context.clicks / context.maxClicks) * 100 : 0;
39
- },
40
- get isComplete() {
41
- const context = getContext();
42
- return context.clicks >= context.maxClicks && context.maxClicks > 0;
43
- }
44
- },
45
-
46
- // Actions - user interactions
47
- actions: {
48
- // Handle block click
49
- handleClick: () => {
50
- const context = getContext();
51
- const { element } = getElement();
52
-
53
- // Increment click counter
54
- context.clicks += 1;
55
- context.lastInteraction = 'click';
56
-
57
- // Trigger animation
58
- if (context.animation !== 'none') {
59
- context.isAnimating = true;
60
- setTimeout(() => {
61
- context.isAnimating = false;
62
- }, 1000);
63
- }
64
-
65
- // Emit custom event
66
- element.dispatchEvent(new CustomEvent('{{slugKebabCase}}:click', {
67
- detail: { clicks: context.clicks }
68
- }));
69
-
70
- // Check if max clicks reached
71
- if (context.maxClicks > 0 && context.clicks >= context.maxClicks) {
72
- element.dispatchEvent(new CustomEvent('{{slugKebabCase}}:complete', {
73
- detail: { totalClicks: context.clicks }
74
- }));
75
- }
76
- },
77
-
78
- // Handle hover events
79
- handleMouseEnter: () => {
80
- const context = getContext();
81
- if (context.interactiveMode === 'hover') {
82
- context.isAnimating = true;
83
- context.lastInteraction = 'hover';
84
- }
85
- },
86
-
87
- handleMouseLeave: () => {
88
- const context = getContext();
89
- if (context.interactiveMode === 'hover') {
90
- context.isAnimating = false;
91
- }
92
- },
93
-
94
- // Toggle visibility
95
- toggleVisibility: () => {
96
- const context = getContext();
97
- context.isVisible = !context.isVisible;
98
- },
99
-
100
- // Reset counter
101
- reset: () => {
102
- const context = getContext();
103
- context.clicks = 0;
104
- context.isAnimating = false;
105
- context.lastInteraction = 'reset';
106
- },
107
-
108
- // Start/stop auto play
109
- toggleAutoPlay: () => {
110
- const context = getContext();
111
- if (context.autoPlayInterval > 0) {
112
- if (context.autoPlayTimer) {
113
- clearInterval(context.autoPlayTimer);
114
- context.autoPlayTimer = null;
115
- } else {
116
- context.autoPlayTimer = setInterval(() => {
117
- context.clicks += 1;
118
- context.isAnimating = true;
119
- setTimeout(() => {
120
- context.isAnimating = false;
121
- }, 500);
122
- }, context.autoPlayInterval);
123
- }
124
- }
125
- }
126
- },
127
-
128
- // Callbacks - lifecycle hooks
129
- callbacks: {
130
- // Initialize on mount
131
- onInit: () => {
132
- const context = getContext();
133
- const { element } = getElement();
134
-
135
- // Set initial state from attributes
136
- context.clicks = parseInt(element.dataset.clicks || '0');
137
- context.isAnimating = element.dataset.isAnimating === 'true';
138
- context.isVisible = element.dataset.isVisible !== 'false';
139
-
140
- // Set up event listeners
141
- element.addEventListener('{{slugKebabCase}}:external-trigger', (event: any) => {
142
- context.clicks = event.detail.clicks || context.clicks + 1;
143
- });
144
- },
145
-
146
- // Log interactions
147
- onInteraction: () => {
148
- const context = getContext();
149
- console.log(`{{slugKebabCase}} interaction:`, {
150
- clicks: context.clicks,
151
- type: context.lastInteraction,
152
- timestamp: new Date().toISOString()
153
- });
154
- },
155
-
156
- // Cleanup on unmount
157
- onDestroy: () => {
158
- const context = getContext();
159
- if (context.autoPlayTimer) {
160
- clearInterval(context.autoPlayTimer);
161
- }
162
- }
163
- }
164
- });
165
-
166
- // Type definitions for TypeScript
167
- declare global {
168
- namespace WordPress {
169
- namespace Interactivity {
170
- interface {{pascalCase}}Context {
171
- clicks: number;
172
- isAnimating: boolean;
173
- isVisible: boolean;
174
- lastInteraction: string;
175
- animation: string;
176
- interactiveMode: string;
177
- maxClicks: number;
178
- autoPlayInterval: number;
179
- autoPlayTimer?: number;
180
- }
181
- }
182
- }
183
- }
@@ -1,87 +0,0 @@
1
- import { useBlockProps, RichText } from '@wordpress/block-editor';
2
- import type { {{pascalCase}}Attributes } from './types';
3
-
4
- export default function Save({ attributes }: { attributes: {{pascalCase}}Attributes }) {
5
- const blockProps = useBlockProps.save({
6
- className: `wp-block-{{slugKebabCase}} wp-block-{{slugKebabCase}}--${attributes.interactiveMode}`,
7
- 'data-wp-interactive': '{{slugKebabCase}}',
8
- 'data-wp-context': JSON.stringify({
9
- clicks: attributes.clickCount,
10
- isAnimating: attributes.isAnimating,
11
- isVisible: attributes.isVisible,
12
- lastInteraction: '',
13
- animation: attributes.animation,
14
- interactiveMode: attributes.interactiveMode,
15
- maxClicks: attributes.maxClicks,
16
- autoPlayInterval: attributes.autoPlayInterval
17
- }),
18
- 'data-clicks': attributes.clickCount,
19
- 'data-is-animating': attributes.isAnimating,
20
- 'data-is-visible': attributes.isVisible,
21
- 'data-unique-id': attributes.uniqueId
22
- });
23
-
24
- return (
25
- <div {...blockProps}>
26
- <div
27
- className={`{{cssClassName}}__content ${attributes.isAnimating ? 'is-animating' : ''}`}
28
- style={{ textAlign: attributes.alignment }}
29
- data-wp-on--click="actions.handleClick"
30
- data-wp-on--mouseenter={attributes.interactiveMode === 'hover' ? 'actions.handleMouseEnter' : undefined}
31
- data-wp-on--mouseleave={attributes.interactiveMode === 'hover' ? 'actions.handleMouseLeave' : undefined}
32
- data-wp-bind--hidden="!state.isVisible"
33
- >
34
- <RichText.Content
35
- tagName="p"
36
- value={attributes.content}
37
- className="{{cssClassName}}__text"
38
- />
39
-
40
- {attributes.showCounter && (
41
- <div className="{{cssClassName}}__counter">
42
- <span className="{{cssClassName}}__counter-label">
43
- Clicks:
44
- </span>
45
- <span
46
- className="{{cssClassName}}__counter-value"
47
- data-wp-text="state.clicks"
48
- >
49
- {attributes.clickCount}
50
- </span>
51
- </div>
52
- )}
53
-
54
- {attributes.maxClicks > 0 && (
55
- <div className="{{cssClassName}}__progress">
56
- <div
57
- className="{{cssClassName}}__progress-bar"
58
- data-wp-style--width="state.progress + '%'"
59
- />
60
- </div>
61
- )}
62
-
63
- <div
64
- className={`{{cssClassName}}__animation ${attributes.animation}`}
65
- data-wp-class="is-active"
66
- />
67
-
68
- {attributes.maxClicks > 0 && (
69
- <div
70
- className="{{cssClassName}}__completion"
71
- data-wp-bind--hidden="!state.isComplete"
72
- >
73
- 🎉 Complete!
74
- </div>
75
- )}
76
-
77
- <button
78
- className="{{cssClassName}}__reset"
79
- data-wp-on--click="actions.reset"
80
- aria-label="Reset counter"
81
- >
82
-
83
- </button>
84
- </div>
85
- </div>
86
- );
87
- }
@@ -1,29 +0,0 @@
1
- import { tags } from "typia";
2
-
3
- export interface {{pascalCase}}Attributes {
4
- content: string & tags.MinLength<1> & tags.MaxLength<1000> & tags.Default<"">;
5
- alignment?: ('left' | 'center' | 'right') & tags.Default<"left">;
6
- isVisible?: boolean & tags.Default<true>;
7
- interactiveMode?: ('click' | 'hover' | 'auto') & tags.Default<"click">;
8
- animation?: ('none' | 'bounce' | 'pulse' | 'shake' | 'flip') & tags.Default<"none">;
9
- clickCount?: number & tags.Default<0>;
10
- isAnimating?: boolean & tags.Default<false>;
11
- showCounter?: boolean & tags.Default<true>;
12
- maxClicks?: number & tags.Default<10>;
13
- autoPlayInterval?: number & tags.Default<0>;
14
- uniqueId?: string & tags.Default<"">;
15
- }
16
-
17
- export interface {{pascalCase}}Context {
18
- clicks: number;
19
- isAnimating: boolean;
20
- isVisible: boolean;
21
- lastInteraction: string;
22
- animationClass: string;
23
- }
24
-
25
- export type {{pascalCase}}ValidationResult = {
26
- isValid: boolean;
27
- errors: string[];
28
- data?: {{pascalCase}}Attributes;
29
- };
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "@wordpress/scripts/config/tsconfig.json",
3
- "compilerOptions": {
4
- "rootDir": "src",
5
- "declarationDir": "build/types"
6
- },
7
- "include": ["src/**/*"],
8
- "exclude": ["build/**/*"]
9
- }