@wp-typia/create 0.1.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.
Files changed (95) hide show
  1. package/README.md +43 -0
  2. package/dist/cli.js +2492 -0
  3. package/dist/runtime/cli-core.js +222 -0
  4. package/dist/runtime/index.js +4 -0
  5. package/dist/runtime/migration-constants.js +14 -0
  6. package/dist/runtime/migration-diff.js +521 -0
  7. package/dist/runtime/migration-fixtures.js +89 -0
  8. package/dist/runtime/migration-manifest.js +129 -0
  9. package/dist/runtime/migration-project.js +167 -0
  10. package/dist/runtime/migration-render.js +267 -0
  11. package/dist/runtime/migration-types.js +1 -0
  12. package/dist/runtime/migration-utils.js +184 -0
  13. package/dist/runtime/migrations.js +232 -0
  14. package/dist/runtime/package-managers.js +135 -0
  15. package/dist/runtime/scaffold.js +334 -0
  16. package/dist/runtime/template-registry.js +75 -0
  17. package/package.json +65 -0
  18. package/templates/advanced/README.md.mustache +150 -0
  19. package/templates/advanced/block.json.mustache +43 -0
  20. package/templates/advanced/index.js +21 -0
  21. package/templates/advanced/package.json.mustache +47 -0
  22. package/templates/advanced/render.php.mustache +83 -0
  23. package/templates/advanced/scripts/lib/typia-metadata-core.ts +1413 -0
  24. package/templates/advanced/scripts/sync-types-to-block-json.ts.mustache +32 -0
  25. package/templates/advanced/src/admin/migration-dashboard.tsx.mustache +315 -0
  26. package/templates/advanced/src/components/ErrorBoundary.tsx.mustache +47 -0
  27. package/templates/advanced/src/deprecated.ts.mustache +2 -0
  28. package/templates/advanced/src/edit.tsx.mustache +97 -0
  29. package/templates/advanced/src/hooks/useDebounce.ts.mustache +20 -0
  30. package/templates/advanced/src/hooks/useLocalStorage.ts.mustache +31 -0
  31. package/templates/advanced/src/hooks.ts.mustache +56 -0
  32. package/templates/advanced/src/index.tsx.mustache +18 -0
  33. package/templates/advanced/src/migration-detector.ts.mustache +9 -0
  34. package/templates/advanced/src/migrations/config.ts.mustache +8 -0
  35. package/templates/advanced/src/migrations/examples/rename-transform-union/README.md.mustache +23 -0
  36. package/templates/advanced/src/migrations/examples/rename-transform-union/fixture.example.json.mustache +36 -0
  37. package/templates/advanced/src/migrations/examples/rename-transform-union/rule.example.ts.mustache +47 -0
  38. package/templates/advanced/src/migrations/fixtures/README.md.mustache +3 -0
  39. package/templates/advanced/src/migrations/generated/deprecated.ts.mustache +3 -0
  40. package/templates/advanced/src/migrations/generated/registry.ts.mustache +9 -0
  41. package/templates/advanced/src/migrations/generated/verify.ts.mustache +1 -0
  42. package/templates/advanced/src/migrations/helpers.ts.mustache +354 -0
  43. package/templates/advanced/src/migrations/index.ts.mustache +616 -0
  44. package/templates/advanced/src/migrations/rules/README.md.mustache +3 -0
  45. package/templates/advanced/src/migrations/versions/README.md.mustache +3 -0
  46. package/templates/advanced/src/save.tsx.mustache +12 -0
  47. package/templates/advanced/src/style.scss.mustache +84 -0
  48. package/templates/advanced/src/types.ts.mustache +46 -0
  49. package/templates/advanced/src/utils/classnames.ts.mustache +51 -0
  50. package/templates/advanced/src/utils/debounce.ts.mustache +37 -0
  51. package/templates/advanced/src/utils/index.ts.mustache +7 -0
  52. package/templates/advanced/src/utils/uuid.ts.mustache +17 -0
  53. package/templates/advanced/src/validators.ts.mustache +39 -0
  54. package/templates/advanced/src/view.ts.mustache +59 -0
  55. package/templates/advanced/tsconfig.json.mustache +20 -0
  56. package/templates/advanced/webpack.config.js.mustache +95 -0
  57. package/templates/basic/package.json.mustache +39 -0
  58. package/templates/basic/scripts/lib/typia-metadata-core.ts +1413 -0
  59. package/templates/basic/scripts/sync-types-to-block-json.ts +25 -0
  60. package/templates/basic/src/block.json +51 -0
  61. package/templates/basic/src/edit.tsx +85 -0
  62. package/templates/basic/src/hooks.ts +75 -0
  63. package/templates/basic/src/index.tsx +37 -0
  64. package/templates/basic/src/save.tsx +27 -0
  65. package/templates/basic/src/style.scss +42 -0
  66. package/templates/basic/src/types.ts +48 -0
  67. package/templates/basic/src/validators.ts +39 -0
  68. package/templates/basic/tsconfig.json +20 -0
  69. package/templates/basic/webpack.config.js +89 -0
  70. package/templates/full/package.json.mustache +40 -0
  71. package/templates/full/scripts/lib/typia-metadata-core.ts +1413 -0
  72. package/templates/full/scripts/sync-types-to-block-json.ts.mustache +32 -0
  73. package/templates/full/src/block.json.mustache +120 -0
  74. package/templates/full/src/edit.tsx.mustache +300 -0
  75. package/templates/full/src/editor.scss.mustache +251 -0
  76. package/templates/full/src/hooks.ts.mustache +141 -0
  77. package/templates/full/src/index.tsx.mustache +27 -0
  78. package/templates/full/src/save.tsx.mustache +39 -0
  79. package/templates/full/src/style.scss.mustache +224 -0
  80. package/templates/full/src/types.ts.mustache +35 -0
  81. package/templates/full/src/validators.ts.mustache +84 -0
  82. package/templates/full/tsconfig.json.mustache +20 -0
  83. package/templates/full/webpack.config.js.mustache +89 -0
  84. package/templates/interactivity/package.json.mustache +41 -0
  85. package/templates/interactivity/scripts/lib/typia-metadata-core.ts +1413 -0
  86. package/templates/interactivity/scripts/sync-types-to-block-json.ts.mustache +32 -0
  87. package/templates/interactivity/src/block.json.mustache +74 -0
  88. package/templates/interactivity/src/edit.tsx.mustache +206 -0
  89. package/templates/interactivity/src/index.tsx.mustache +20 -0
  90. package/templates/interactivity/src/interactivity.ts.mustache +183 -0
  91. package/templates/interactivity/src/save.tsx.mustache +87 -0
  92. package/templates/interactivity/src/style.scss.mustache +60 -0
  93. package/templates/interactivity/src/types.ts.mustache +30 -0
  94. package/templates/interactivity/tsconfig.json.mustache +20 -0
  95. package/templates/interactivity/webpack.config.js.mustache +89 -0
@@ -0,0 +1,32 @@
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, typia.manifest.json, and typia-validator.php 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
+ if (result.phpGenerationWarnings.length > 0) {
22
+ console.warn("⚠️ Some Typia constraints are not yet enforced by typia-validator.php:");
23
+ for (const warning of result.phpGenerationWarnings) {
24
+ console.warn(` - ${warning}`);
25
+ }
26
+ }
27
+ }
28
+
29
+ main().catch((error) => {
30
+ console.error("❌ Type sync failed:", error);
31
+ process.exit(1);
32
+ });
@@ -0,0 +1,120 @@
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
+ "alignWide": true,
15
+ "anchor": true,
16
+ "className": true,
17
+ "customClassName": true,
18
+ "color": {
19
+ "gradients": true,
20
+ "link": true,
21
+ "text": true,
22
+ "background": true
23
+ },
24
+ "spacing": {
25
+ "margin": true,
26
+ "padding": true,
27
+ "blockGap": true
28
+ },
29
+ "typography": {
30
+ "fontSize": true,
31
+ "lineHeight": true,
32
+ "fontStyle": true,
33
+ "fontWeight": true,
34
+ "letterSpacing": true,
35
+ "textAlign": true,
36
+ "textDecoration": true,
37
+ "textTransform": true,
38
+ "writingMode": true
39
+ },
40
+ "dimensions": {
41
+ "minHeight": true
42
+ },
43
+ "position": {
44
+ "sticky": true,
45
+ "fixed": true
46
+ },
47
+ "interactivity": true
48
+ },
49
+ "attributes": {
50
+ "content": {
51
+ "type": "string",
52
+ "source": "html",
53
+ "selector": ".{{cssClassName}}__content",
54
+ "default": ""
55
+ },
56
+ "alignment": {
57
+ "type": "string",
58
+ "enum": ["left", "center", "right", "justify"],
59
+ "default": "left"
60
+ },
61
+ "isVisible": {
62
+ "type": "boolean",
63
+ "default": true
64
+ },
65
+ "fontSize": {
66
+ "type": "string",
67
+ "enum": ["small", "medium", "large", "xlarge"],
68
+ "default": "medium"
69
+ },
70
+ "textColor": {
71
+ "type": "string",
72
+ "default": ""
73
+ },
74
+ "backgroundColor": {
75
+ "type": "string",
76
+ "default": ""
77
+ },
78
+ "padding": {
79
+ "type": "object",
80
+ "default": {
81
+ "top": 0,
82
+ "right": 0,
83
+ "bottom": 0,
84
+ "left": 0
85
+ }
86
+ },
87
+ "borderRadius": {
88
+ "type": "number",
89
+ "default": 0
90
+ },
91
+ "shadow": {
92
+ "type": "object",
93
+ "default": {
94
+ "enabled": false,
95
+ "x": 0,
96
+ "y": 4,
97
+ "blur": 8,
98
+ "spread": 0,
99
+ "color": "rgba(0, 0, 0, 0.1)"
100
+ }
101
+ },
102
+ "animation": {
103
+ "type": "string",
104
+ "enum": ["none", "fadeIn", "slideUp", "slideDown", "zoomIn"],
105
+ "default": "none"
106
+ },
107
+ "customCSS": {
108
+ "type": "string",
109
+ "default": ""
110
+ },
111
+ "uniqueId": {
112
+ "type": "string",
113
+ "default": ""
114
+ }
115
+ },
116
+ "textdomain": "{{slugSnakeCase}}",
117
+ "editorScript": "file:./index.js",
118
+ "editorStyle": "file:./index.css",
119
+ "style": "file:./style-index.css"
120
+ }
@@ -0,0 +1,300 @@
1
+ import { __ } from '@wordpress/i18n';
2
+ import { useBlockProps, InspectorControls, RichText, BlockControls, AlignmentToolbar } from '@wordpress/block-editor';
3
+ import { PanelBody, TextControl, SelectControl, ToggleControl, RangeControl, ColorPicker, ColorPalette, TabPanel, Disabled, Notice } from '@wordpress/components';
4
+ import { useState, useEffect } from '@wordpress/element';
5
+ import { use{{pascalCase}}Attributes, useColorScheme } from './hooks';
6
+ import type { {{pascalCase}}Attributes } from './types';
7
+
8
+ export default function Edit({ attributes, setAttributes, isSelected }: {
9
+ attributes: {{pascalCase}}Attributes;
10
+ setAttributes: (attrs: Partial<{{pascalCase}}Attributes>) => void;
11
+ isSelected: boolean;
12
+ }) {
13
+ const { attributes: validatedAttrs, updateAttribute, validationErrors, isValid } = use{{pascalCase}}Attributes(attributes);
14
+ const { getColorVariable } = useColorScheme();
15
+ const [activeTab, setActiveTab] = useState('content');
16
+
17
+ const blockProps = useBlockProps({
18
+ className: `wp-block-{{slugKebabCase}} wp-block-{{slugKebabCase}}--${validatedAttrs.fontSize} wp-block-{{slugKebabCase}}--align-${validatedAttrs.alignment}`,
19
+ style: {
20
+ color: getColorVariable(validatedAttrs.textColor),
21
+ backgroundColor: getColorVariable(validatedAttrs.backgroundColor),
22
+ padding: `${validatedAttrs.padding.top}px ${validatedAttrs.padding.right}px ${validatedAttrs.padding.bottom}px ${validatedAttrs.padding.left}px`,
23
+ borderRadius: `${validatedAttrs.borderRadius}px`,
24
+ boxShadow: validatedAttrs.shadow.enabled
25
+ ? `${validatedAttrs.shadow.x}px ${validatedAttrs.shadow.y}px ${validatedAttrs.shadow.blur}px ${validatedAttrs.shadow.spread}px ${validatedAttrs.shadow.color}`
26
+ : 'none',
27
+ display: validatedAttrs.isVisible ? 'block' : 'none',
28
+ opacity: validatedAttrs.isVisible ? 1 : 0.5,
29
+ }
30
+ });
31
+
32
+ useEffect(() => {
33
+ if (isValid && validatedAttrs !== attributes) {
34
+ setAttributes(validatedAttrs);
35
+ }
36
+ }, [validatedAttrs, isValid, attributes, setAttributes]);
37
+
38
+ const contentTabs = [
39
+ {
40
+ name: 'content',
41
+ title: __('Content', '{{slugSnakeCase}}'),
42
+ className: 'tab-content'
43
+ },
44
+ {
45
+ name: 'style',
46
+ title: __('Style', '{{slugSnakeCase}}'),
47
+ className: 'tab-style'
48
+ },
49
+ {
50
+ name: 'advanced',
51
+ title: __('Advanced', '{{slugSnakeCase}}'),
52
+ className: 'tab-advanced'
53
+ }
54
+ ];
55
+
56
+ return (
57
+ <>
58
+ <BlockControls>
59
+ <AlignmentToolbar
60
+ value={validatedAttrs.alignment}
61
+ onChange={(value) => updateAttribute('alignment', value || 'left')}
62
+ />
63
+ </BlockControls>
64
+
65
+ <InspectorControls>
66
+ <TabPanel
67
+ tabs={contentTabs}
68
+ onSelect={setActiveTab}
69
+ className="wp-block-{{slugKebabCase}}__tabs"
70
+ >
71
+ {(tab) => {
72
+ if (tab.name === 'content') {
73
+ return (
74
+ <>
75
+ <PanelBody title={__('Text Settings', '{{slugSnakeCase}}')}>
76
+ <TextControl
77
+ label={__('Unique ID', '{{slugSnakeCase}}')}
78
+ value={validatedAttrs.uniqueId}
79
+ onChange={(value) => updateAttribute('uniqueId', value)}
80
+ help={__('Optional unique identifier for this block', '{{slugSnakeCase}}')}
81
+ />
82
+
83
+ <ToggleControl
84
+ label={__('Visible', '{{slugSnakeCase}}')}
85
+ checked={validatedAttrs.isVisible}
86
+ onChange={(value) => updateAttribute('isVisible', value)}
87
+ />
88
+ </PanelBody>
89
+
90
+ <PanelBody title={__('Typography', '{{slugSnakeCase}}')}>
91
+ <SelectControl
92
+ label={__('Font Size', '{{slugSnakeCase}}')}
93
+ value={validatedAttrs.fontSize}
94
+ options={[
95
+ { label: __('Small', '{{slugSnakeCase}}'), value: 'small' },
96
+ { label: __('Medium', '{{slugSnakeCase}}'), value: 'medium' },
97
+ { label: __('Large', '{{slugSnakeCase}}'), value: 'large' },
98
+ { label: __('Extra Large', '{{slugSnakeCase}}'), value: 'xlarge' },
99
+ ]}
100
+ onChange={(value) => updateAttribute('fontSize', value)}
101
+ />
102
+ </PanelBody>
103
+ </>
104
+ );
105
+ }
106
+
107
+ if (tab.name === 'style') {
108
+ return (
109
+ <>
110
+ <PanelBody title={__('Colors', '{{slugSnakeCase}}')}>
111
+ <div className="components-base-control">
112
+ <label className="components-base-control__label">
113
+ {__('Text Color', '{{slugSnakeCase}}')}
114
+ </label>
115
+ <ColorPalette
116
+ value={validatedAttrs.textColor}
117
+ onChange={(value) => updateAttribute('textColor', value)}
118
+ disableCustomColors={false}
119
+ clearable={true}
120
+ />
121
+ </div>
122
+
123
+ <div className="components-base-control" style={{ marginTop: '1em' }}>
124
+ <label className="components-base-control__label">
125
+ {__('Background Color', '{{slugSnakeCase}}')}
126
+ </label>
127
+ <ColorPalette
128
+ value={validatedAttrs.backgroundColor}
129
+ onChange={(value) => updateAttribute('backgroundColor', value)}
130
+ disableCustomColors={false}
131
+ clearable={true}
132
+ />
133
+ </div>
134
+ </PanelBody>
135
+
136
+ <PanelBody title={__('Spacing', '{{slugSnakeCase}}')}>
137
+ <RangeControl
138
+ label={__('Border Radius', '{{slugSnakeCase}}')}
139
+ value={validatedAttrs.borderRadius}
140
+ onChange={(value) => updateAttribute('borderRadius', value)}
141
+ min={0}
142
+ max={50}
143
+ />
144
+
145
+ <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1em', marginTop: '1em' }}>
146
+ <RangeControl
147
+ label={__('Padding Top', '{{slugSnakeCase}}')}
148
+ value={validatedAttrs.padding.top}
149
+ onChange={(value) => updateAttribute('padding', { ...validatedAttrs.padding, top: value })}
150
+ min={0}
151
+ max={100}
152
+ />
153
+ <RangeControl
154
+ label={__('Padding Right', '{{slugSnakeCase}}')}
155
+ value={validatedAttrs.padding.right}
156
+ onChange={(value) => updateAttribute('padding', { ...validatedAttrs.padding, right: value })}
157
+ min={0}
158
+ max={100}
159
+ />
160
+ <RangeControl
161
+ label={__('Padding Bottom', '{{slugSnakeCase}}')}
162
+ value={validatedAttrs.padding.bottom}
163
+ onChange={(value) => updateAttribute('padding', { ...validatedAttrs.padding, bottom: value })}
164
+ min={0}
165
+ max={100}
166
+ />
167
+ <RangeControl
168
+ label={__('Padding Left', '{{slugSnakeCase}}')}
169
+ value={validatedAttrs.padding.left}
170
+ onChange={(value) => updateAttribute('padding', { ...validatedAttrs.padding, left: value })}
171
+ min={0}
172
+ max={100}
173
+ />
174
+ </div>
175
+ </PanelBody>
176
+
177
+ <PanelBody title={__('Shadow', '{{slugSnakeCase}}')}>
178
+ <ToggleControl
179
+ label={__('Enable Shadow', '{{slugSnakeCase}}')}
180
+ checked={validatedAttrs.shadow.enabled}
181
+ onChange={(value) => updateAttribute('shadow', { ...validatedAttrs.shadow, enabled: value })}
182
+ />
183
+
184
+ {validatedAttrs.shadow.enabled && (
185
+ <>
186
+ <RangeControl
187
+ label={__('Horizontal Offset', '{{slugSnakeCase}}')}
188
+ value={validatedAttrs.shadow.x}
189
+ onChange={(value) => updateAttribute('shadow', { ...validatedAttrs.shadow, x: value })}
190
+ min={-50}
191
+ max={50}
192
+ />
193
+ <RangeControl
194
+ label={__('Vertical Offset', '{{slugSnakeCase}}')}
195
+ value={validatedAttrs.shadow.y}
196
+ onChange={(value) => updateAttribute('shadow', { ...validatedAttrs.shadow, y: value })}
197
+ min={-50}
198
+ max={50}
199
+ />
200
+ <RangeControl
201
+ label={__('Blur', '{{slugSnakeCase}}')}
202
+ value={validatedAttrs.shadow.blur}
203
+ onChange={(value) => updateAttribute('shadow', { ...validatedAttrs.shadow, blur: value })}
204
+ min={0}
205
+ max={100}
206
+ />
207
+ <RangeControl
208
+ label={__('Spread', '{{slugSnakeCase}}')}
209
+ value={validatedAttrs.shadow.spread}
210
+ onChange={(value) => updateAttribute('shadow', { ...validatedAttrs.shadow, spread: value })}
211
+ min={-50}
212
+ max={50}
213
+ />
214
+ <div className="components-base-control">
215
+ <label className="components-base-control__label">
216
+ {__('Shadow Color', '{{slugSnakeCase}}')}
217
+ </label>
218
+ <ColorPicker
219
+ color={validatedAttrs.shadow.color}
220
+ onChangeComplete={(value) => updateAttribute('shadow', { ...validatedAttrs.shadow, color: value.hex })}
221
+ disableAlpha={false}
222
+ />
223
+ </div>
224
+ </>
225
+ )}
226
+ </PanelBody>
227
+
228
+ <PanelBody title={__('Animation', '{{slugSnakeCase}}')}>
229
+ <SelectControl
230
+ label={__('Animation Type', '{{slugSnakeCase}}')}
231
+ value={validatedAttrs.animation}
232
+ options={[
233
+ { label: __('None', '{{slugSnakeCase}}'), value: 'none' },
234
+ { label: __('Fade In', '{{slugSnakeCase}}'), value: 'fadeIn' },
235
+ { label: __('Slide Up', '{{slugSnakeCase}}'), value: 'slideUp' },
236
+ { label: __('Slide Down', '{{slugSnakeCase}}'), value: 'slideDown' },
237
+ { label: __('Zoom In', '{{slugSnakeCase}}'), value: 'zoomIn' },
238
+ ]}
239
+ onChange={(value) => updateAttribute('animation', value)}
240
+ />
241
+ </PanelBody>
242
+ </>
243
+ );
244
+ }
245
+
246
+ if (tab.name === 'advanced') {
247
+ return (
248
+ <>
249
+ <PanelBody title={__('Advanced', '{{slugSnakeCase}}')}>
250
+ {!isValid && validationErrors.length > 0 && (
251
+ <Notice status="error" isDismissible={false}>
252
+ <strong>{__('Validation Errors:', '{{slugSnakeCase}}')}</strong>
253
+ <ul>
254
+ {validationErrors.map((error, index) => (
255
+ <li key={index}>{error}</li>
256
+ ))}
257
+ </ul>
258
+ </Notice>
259
+ )}
260
+
261
+ <TextControl
262
+ label={__('Custom CSS', '{{slugSnakeCase}}')}
263
+ value={validatedAttrs.customCSS}
264
+ onChange={(value) => updateAttribute('customCSS', value)}
265
+ multiline={5}
266
+ help={__('Add custom CSS classes or inline styles', '{{slugSnakeCase}}')}
267
+ />
268
+ </PanelBody>
269
+ </>
270
+ );
271
+ }
272
+
273
+ return null;
274
+ }}
275
+ </TabPanel>
276
+ </InspectorControls>
277
+
278
+ <div {...blockProps}>
279
+ {isSelected && validatedAttrs.animation !== 'none' && (
280
+ <div className="wp-block-{{slugKebabCase}}__animation-preview">
281
+ {__('Animation Preview:', '{{slugSnakeCase}}')} {validatedAttrs.animation}
282
+ </div>
283
+ )}
284
+
285
+ <div
286
+ className={`{{cssClassName}}__content {{cssClassName}}__content--${validatedAttrs.fontSize}`}
287
+ style={{ textAlign: validatedAttrs.alignment }}
288
+ >
289
+ <RichText
290
+ tagName="p"
291
+ value={validatedAttrs.content}
292
+ onChange={(value) => updateAttribute('content', value)}
293
+ placeholder={__('{{title}} – hello from the editor!', '{{slugSnakeCase}}')}
294
+ allowedFormats={['core/bold', 'core/italic', 'core/link', 'core/strikethrough']}
295
+ />
296
+ </div>
297
+ </div>
298
+ </>
299
+ );
300
+ }
@@ -0,0 +1,251 @@
1
+ /**
2
+ * {{title}} Block Editor Styles
3
+ */
4
+
5
+ .wp-block-{{slugKebabCase}} {
6
+ // Editor-specific styles
7
+ border: 1px dashed #e0e0e0;
8
+ padding: 1em;
9
+ min-height: 60px;
10
+ position: relative;
11
+
12
+ // Visual indicator when block is selected
13
+ &.is-selected {
14
+ border-color: var(--wp-admin-theme-color, #0073aa);
15
+ background-color: rgba(var(--wp-admin-theme-color--rgb, 0, 115, 170), 0.04);
16
+ }
17
+
18
+ // Animation preview indicator
19
+ &__animation-preview {
20
+ position: absolute;
21
+ top: -30px;
22
+ left: 0;
23
+ font-size: 11px;
24
+ color: #757575;
25
+ background: #fff;
26
+ padding: 2px 6px;
27
+ border-radius: 2px;
28
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
29
+ z-index: 10;
30
+ }
31
+
32
+ // Content editor styles
33
+ .{{cssClassName}}__content {
34
+ min-height: 1em;
35
+
36
+ // Rich text editor styles
37
+ .block-editor-rich-text__editable {
38
+ outline: none;
39
+
40
+ &:focus {
41
+ box-shadow: 0 0 0 1px var(--wp-admin-theme-color, #0073aa);
42
+ border-radius: 2px;
43
+ padding: 0 2px;
44
+ }
45
+
46
+ // Placeholder styles
47
+ &[data-is-placeholder-visible="true"] {
48
+ color: #757575;
49
+ font-style: italic;
50
+ }
51
+ }
52
+
53
+ // Link styles in editor
54
+ a {
55
+ color: var(--wp-admin-theme-color, #0073aa);
56
+ text-decoration: underline;
57
+
58
+ &:hover {
59
+ color: var(--wp-admin-theme-color--hover, #005a87);
60
+ }
61
+ }
62
+ }
63
+
64
+ // Tab panel styles in inspector
65
+ &__tabs {
66
+ .components-tab-panel__tabs {
67
+ border-bottom: 1px solid #e0e0e0;
68
+ margin-bottom: 1em;
69
+ }
70
+
71
+ .components-tab-panel__tab {
72
+ padding: 0.5em 1em;
73
+ margin-bottom: -1px;
74
+ border-bottom: 2px solid transparent;
75
+ cursor: pointer;
76
+
77
+ &:hover {
78
+ background-color: #f5f5f5;
79
+ }
80
+
81
+ &.is-active-tab {
82
+ border-bottom-color: var(--wp-admin-theme-color, #0073aa);
83
+ color: var(--wp-admin-theme-color, #0073aa);
84
+ }
85
+ }
86
+ }
87
+
88
+ // Inspector controls enhancements
89
+ .components-panel__body {
90
+ .components-base-control {
91
+ margin-bottom: 1em;
92
+
93
+ &:last-child {
94
+ margin-bottom: 0;
95
+ }
96
+ }
97
+
98
+ // Color picker enhancements
99
+ .components-color-picker {
100
+ margin-top: 0.5em;
101
+ }
102
+
103
+ // Range control enhancements
104
+ .components-range-control {
105
+ .components-range-control__slider {
106
+ margin: 0 10px;
107
+ }
108
+
109
+ .components-range-control__number {
110
+ width: 60px;
111
+ }
112
+ }
113
+
114
+ // Toggle control enhancements
115
+ .components-toggle-control {
116
+ .components-toggle-control__label {
117
+ font-weight: 500;
118
+ }
119
+ }
120
+ }
121
+
122
+ // Validation error styles
123
+ .components-notice {
124
+ &.is-error {
125
+ border-left-color: #cc1818;
126
+ background-color: #fcf0f1;
127
+
128
+ ul {
129
+ margin: 0.5em 0;
130
+ padding-left: 1.5em;
131
+
132
+ li {
133
+ margin-bottom: 0.25em;
134
+ font-size: 12px;
135
+ }
136
+ }
137
+ }
138
+ }
139
+
140
+ // Shadow preview
141
+ &__shadow-preview {
142
+ width: 100%;
143
+ height: 60px;
144
+ border: 1px solid #e0e0e0;
145
+ border-radius: 4px;
146
+ margin-top: 0.5em;
147
+ display: flex;
148
+ align-items: center;
149
+ justify-content: center;
150
+ background: white;
151
+ position: relative;
152
+ overflow: hidden;
153
+
154
+ &::before {
155
+ content: '';
156
+ position: absolute;
157
+ top: 50%;
158
+ left: 50%;
159
+ transform: translate(-50%, -50%);
160
+ width: 30px;
161
+ height: 30px;
162
+ background: var(--wp-admin-theme-color, #0073aa);
163
+ border-radius: 4px;
164
+ }
165
+ }
166
+
167
+ // Padding preview
168
+ &__padding-preview {
169
+ display: grid;
170
+ grid-template-columns: 1fr 1fr;
171
+ grid-template-rows: 1fr 1fr;
172
+ gap: 5px;
173
+ width: 120px;
174
+ height: 120px;
175
+ margin: 1em auto;
176
+ border: 1px solid #e0e0e0;
177
+
178
+ > div {
179
+ background: #f5f5f5;
180
+ display: flex;
181
+ align-items: center;
182
+ justify-content: center;
183
+ font-size: 10px;
184
+ color: #757575;
185
+
186
+ &.center {
187
+ background: var(--wp-admin-theme-color, #0073aa);
188
+ color: white;
189
+ }
190
+ }
191
+ }
192
+
193
+ // Block appender styles
194
+ &.block-list-appender {
195
+ min-height: 100px;
196
+ display: flex;
197
+ align-items: center;
198
+ justify-content: center;
199
+ border: 2px dashed #e0e0e0;
200
+ background: #f9f9f9;
201
+ cursor: pointer;
202
+
203
+ &:hover {
204
+ border-color: var(--wp-admin-theme-color, #0073aa);
205
+ background: rgba(var(--wp-admin-theme-color--rgb, 0, 115, 170), 0.04);
206
+ }
207
+
208
+ .block-list-appender__toggle {
209
+ margin: 0;
210
+ }
211
+ }
212
+
213
+ // Multi-selection styles
214
+ &.is-multi-selected {
215
+ background-color: rgba(var(--wp-admin-theme-color--rgb, 0, 115, 170), 0.08);
216
+ border-color: var(--wp-admin-theme-color, #0073aa);
217
+ }
218
+
219
+ // Highlight when dragging
220
+ &.is-dragging {
221
+ opacity: 0.5;
222
+ }
223
+
224
+ // Drop zone indicator
225
+ &.is-drop-target {
226
+ background-color: rgba(var(--wp-admin-theme-color--rgb, 0, 115, 170), 0.12);
227
+ border-color: var(--wp-admin-theme-color, #0073aa);
228
+ border-style: solid;
229
+ }
230
+
231
+ // Responsive preview in editor
232
+ @media (max-width: 768px) {
233
+ padding: 0.5em;
234
+ min-height: 40px;
235
+
236
+ .{{cssClassName}}__content {
237
+ font-size: 0.9em;
238
+ }
239
+ }
240
+ }
241
+
242
+ // Block toolbar styles
243
+ .block-editor-block-toolbar {
244
+ .wp-block-{{slugKebab-case}}__toolbar {
245
+ .components-button {
246
+ font-size: 12px;
247
+ padding: 0 6px;
248
+ height: 32px;
249
+ }
250
+ }
251
+ }