@wp-typia/project-tools 0.16.2 → 0.16.5

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 (80) hide show
  1. package/README.md +13 -0
  2. package/dist/runtime/block-generator-service.d.ts +102 -0
  3. package/dist/runtime/block-generator-service.js +268 -0
  4. package/dist/runtime/built-in-block-artifacts.d.ts +37 -0
  5. package/dist/runtime/built-in-block-artifacts.js +1203 -0
  6. package/dist/runtime/built-in-block-code-artifacts.d.ts +31 -0
  7. package/dist/runtime/built-in-block-code-artifacts.js +137 -0
  8. package/dist/runtime/built-in-block-non-ts-artifacts.d.ts +18 -0
  9. package/dist/runtime/built-in-block-non-ts-artifacts.js +563 -0
  10. package/dist/runtime/cli-doctor.js +10 -5
  11. package/dist/runtime/index.d.ts +2 -0
  12. package/dist/runtime/index.js +1 -0
  13. package/dist/runtime/scaffold-apply-utils.d.ts +47 -0
  14. package/dist/runtime/scaffold-apply-utils.js +405 -0
  15. package/dist/runtime/scaffold-identifiers.d.ts +34 -0
  16. package/dist/runtime/scaffold-identifiers.js +82 -0
  17. package/dist/runtime/scaffold.js +33 -0
  18. package/dist/runtime/starter-manifests.d.ts +3 -2
  19. package/dist/runtime/starter-manifests.js +15 -365
  20. package/dist/runtime/template-builtins.d.ts +9 -0
  21. package/dist/runtime/template-builtins.js +31 -1
  22. package/dist/runtime/template-render.d.ts +5 -0
  23. package/dist/runtime/template-render.js +13 -3
  24. package/dist/runtime/template-source.js +9 -3
  25. package/package.json +2 -2
  26. package/templates/_shared/compound/persistence/scripts/block-config.ts.mustache +4 -4
  27. package/templates/_shared/persistence/core/scripts/sync-rest-contracts.ts.mustache +4 -4
  28. package/templates/_shared/base/src/hooks.ts.mustache +0 -19
  29. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/block.json.mustache +0 -52
  30. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/edit.tsx.mustache +0 -123
  31. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/hooks.ts.mustache +0 -11
  32. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/interactivity.ts.mustache +0 -305
  33. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/render.php.mustache +0 -152
  34. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/save.tsx.mustache +0 -3
  35. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/types.ts.mustache +0 -61
  36. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/validators.ts.mustache +0 -43
  37. package/templates/_shared/persistence/core/src/index.tsx.mustache +0 -25
  38. package/templates/_shared/persistence/core/src/interactivity.ts.mustache +0 -308
  39. package/templates/_shared/persistence/core/src/save.tsx.mustache +0 -5
  40. package/templates/_shared/persistence/core/src/validators.ts.mustache +0 -43
  41. package/templates/basic/src/block.json.mustache +0 -51
  42. package/templates/basic/src/edit.tsx.mustache +0 -128
  43. package/templates/basic/src/editor.scss.mustache +0 -8
  44. package/templates/basic/src/hooks.ts.mustache +0 -18
  45. package/templates/basic/src/index.tsx.mustache +0 -45
  46. package/templates/basic/src/render.php.mustache +0 -19
  47. package/templates/basic/src/save.tsx.mustache +0 -30
  48. package/templates/basic/src/style.scss.mustache +0 -40
  49. package/templates/basic/src/types.ts.mustache +0 -56
  50. package/templates/basic/src/validators.ts.mustache +0 -37
  51. package/templates/compound/src/blocks/{{slugKebabCase}}/block.json.mustache +0 -37
  52. package/templates/compound/src/blocks/{{slugKebabCase}}/children.ts.mustache +0 -25
  53. package/templates/compound/src/blocks/{{slugKebabCase}}/edit.tsx.mustache +0 -93
  54. package/templates/compound/src/blocks/{{slugKebabCase}}/hooks.ts.mustache +0 -11
  55. package/templates/compound/src/blocks/{{slugKebabCase}}/index.tsx.mustache +0 -25
  56. package/templates/compound/src/blocks/{{slugKebabCase}}/save.tsx.mustache +0 -32
  57. package/templates/compound/src/blocks/{{slugKebabCase}}/style.scss.mustache +0 -31
  58. package/templates/compound/src/blocks/{{slugKebabCase}}/types.ts.mustache +0 -18
  59. package/templates/compound/src/blocks/{{slugKebabCase}}/validators.ts.mustache +0 -35
  60. package/templates/compound/src/blocks/{{slugKebabCase}}-item/block.json.mustache +0 -35
  61. package/templates/compound/src/blocks/{{slugKebabCase}}-item/edit.tsx.mustache +0 -50
  62. package/templates/compound/src/blocks/{{slugKebabCase}}-item/hooks.ts.mustache +0 -11
  63. package/templates/compound/src/blocks/{{slugKebabCase}}-item/index.tsx.mustache +0 -25
  64. package/templates/compound/src/blocks/{{slugKebabCase}}-item/save.tsx.mustache +0 -24
  65. package/templates/compound/src/blocks/{{slugKebabCase}}-item/types.ts.mustache +0 -17
  66. package/templates/compound/src/blocks/{{slugKebabCase}}-item/validators.ts.mustache +0 -35
  67. package/templates/interactivity/src/block.json.mustache +0 -74
  68. package/templates/interactivity/src/edit.tsx.mustache +0 -270
  69. package/templates/interactivity/src/editor.scss.mustache +0 -8
  70. package/templates/interactivity/src/index.tsx.mustache +0 -33
  71. package/templates/interactivity/src/interactivity.ts.mustache +0 -152
  72. package/templates/interactivity/src/save.tsx.mustache +0 -101
  73. package/templates/interactivity/src/style.scss.mustache +0 -60
  74. package/templates/interactivity/src/types.ts.mustache +0 -32
  75. package/templates/interactivity/src/validators.ts.mustache +0 -47
  76. package/templates/persistence/src/block.json.mustache +0 -52
  77. package/templates/persistence/src/edit.tsx.mustache +0 -165
  78. package/templates/persistence/src/render.php.mustache +0 -120
  79. package/templates/persistence/src/style.scss.mustache +0 -46
  80. package/templates/persistence/src/types.ts.mustache +0 -59
@@ -1,123 +0,0 @@
1
- import { __ } from '@wordpress/i18n';
2
- import {
3
- InspectorControls,
4
- InnerBlocks,
5
- RichText,
6
- useBlockProps,
7
- } from '@wordpress/block-editor';
8
- import {
9
- Notice,
10
- PanelBody,
11
- TextControl,
12
- ToggleControl,
13
- } from '@wordpress/components';
14
-
15
- import {
16
- ALLOWED_CHILD_BLOCKS,
17
- DEFAULT_CHILD_TEMPLATE,
18
- } from './children';
19
- import { useTypiaValidation } from './hooks';
20
- import type { {{pascalCase}}Attributes } from './types';
21
- import {
22
- createAttributeUpdater,
23
- validate{{pascalCase}}Attributes,
24
- } from './validators';
25
-
26
- export default function Edit( {
27
- attributes,
28
- setAttributes,
29
- }: {
30
- attributes: {{pascalCase}}Attributes;
31
- setAttributes: ( attrs: Partial< {{pascalCase}}Attributes > ) => void;
32
- } ) {
33
- const { errorMessages, isValid } = useTypiaValidation(
34
- attributes,
35
- validate{{pascalCase}}Attributes
36
- );
37
- const updateAttribute = createAttributeUpdater( attributes, setAttributes );
38
- const blockProps = useBlockProps( {
39
- className: '{{cssClassName}}',
40
- } );
41
-
42
- return (
43
- <>
44
- <InspectorControls>
45
- <PanelBody title={ __( 'Compound Settings', '{{textDomain}}' ) }>
46
- <ToggleControl
47
- label={ __( 'Show dividers between items', '{{textDomain}}' ) }
48
- checked={ attributes.showDividers ?? true }
49
- onChange={ ( value ) => updateAttribute( 'showDividers', value ) }
50
- />
51
- <ToggleControl
52
- label={ __( 'Show persisted count', '{{textDomain}}' ) }
53
- checked={ attributes.showCount ?? true }
54
- onChange={ ( value ) => updateAttribute( 'showCount', value ) }
55
- />
56
- <TextControl
57
- label={ __( 'Button label', '{{textDomain}}' ) }
58
- value={ attributes.buttonLabel ?? 'Persist Count' }
59
- onChange={ ( buttonLabel ) => updateAttribute( 'buttonLabel', buttonLabel ) }
60
- />
61
- <TextControl
62
- label={ __( 'Resource key', '{{textDomain}}' ) }
63
- value={ attributes.resourceKey ?? '' }
64
- onChange={ ( resourceKey ) => updateAttribute( 'resourceKey', resourceKey ) }
65
- help={ __( 'Stable key used by the persisted counter endpoint.', '{{textDomain}}' ) }
66
- />
67
- <Notice status="info" isDismissible={ false }>
68
- { __( 'Storage mode: {{dataStorageMode}}', '{{textDomain}}' ) }
69
- </Notice>
70
- <Notice status="info" isDismissible={ false }>
71
- { __( 'Persistence policy: {{persistencePolicy}}', '{{textDomain}}' ) }
72
- </Notice>
73
- </PanelBody>
74
- { ! isValid && (
75
- <PanelBody title={ __( 'Validation Errors', '{{textDomain}}' ) } initialOpen>
76
- { errorMessages.map( ( error, index ) => (
77
- <Notice key={ index } status="error" isDismissible={ false }>
78
- { error }
79
- </Notice>
80
- ) ) }
81
- </PanelBody>
82
- ) }
83
- </InspectorControls>
84
- <div { ...blockProps }>
85
- <RichText
86
- tagName="h3"
87
- className="{{cssClassName}}__heading"
88
- value={ attributes.heading }
89
- onChange={ ( heading ) => updateAttribute( 'heading', heading ) }
90
- placeholder={ __( {{titleJson}}, '{{textDomain}}' ) }
91
- />
92
- <RichText
93
- tagName="p"
94
- className="{{cssClassName}}__intro"
95
- value={ attributes.intro ?? '' }
96
- onChange={ ( intro ) => updateAttribute( 'intro', intro ) }
97
- placeholder={ __(
98
- 'Add and reorder internal items inside this compound block.',
99
- '{{textDomain}}'
100
- ) }
101
- />
102
- { ! isValid && (
103
- <Notice status="error" isDismissible={ false }>
104
- <ul>
105
- { errorMessages.map( ( error, index ) => <li key={ index }>{ error }</li> ) }
106
- </ul>
107
- </Notice>
108
- ) }
109
- <p className="{{cssClassName}}__meta">
110
- { __( 'Resource key:', '{{textDomain}}' ) } { attributes.resourceKey || '—' }
111
- </p>
112
- <div className="{{cssClassName}}__items">
113
- <InnerBlocks
114
- allowedBlocks={ ALLOWED_CHILD_BLOCKS }
115
- renderAppender={ InnerBlocks.ButtonBlockAppender }
116
- template={ DEFAULT_CHILD_TEMPLATE }
117
- templateLock={ false }
118
- />
119
- </div>
120
- </div>
121
- </>
122
- );
123
- }
@@ -1,11 +0,0 @@
1
- export {
2
- formatValidationError,
3
- formatValidationErrors,
4
- useTypiaValidation,
5
- } from '../../hooks';
6
-
7
- export type {
8
- TypiaValidationError,
9
- ValidationResult,
10
- ValidationState,
11
- } from '../../hooks';
@@ -1,305 +0,0 @@
1
- import { getContext, store } from '@wordpress/interactivity';
2
- import { generatePublicWriteRequestId } from '@wp-typia/block-runtime/identifiers';
3
-
4
- import { fetchBootstrap, fetchState, writeState } from './api';
5
- import type {
6
- {{pascalCase}}ClientState,
7
- {{pascalCase}}Context,
8
- {{pascalCase}}State,
9
- } from './types';
10
-
11
- function hasExpiredPublicWriteToken(
12
- expiresAt?: number
13
- ): boolean {
14
- return (
15
- typeof expiresAt === 'number' &&
16
- expiresAt > 0 &&
17
- Date.now() >= expiresAt * 1000
18
- );
19
- }
20
-
21
- function getWriteBlockedMessage(
22
- context: {{pascalCase}}Context
23
- ): string {
24
- return context.persistencePolicy === 'authenticated'
25
- ? 'Sign in to persist this counter.'
26
- : 'Public writes are temporarily unavailable.';
27
- }
28
-
29
- const BOOTSTRAP_MAX_ATTEMPTS = 3;
30
- const BOOTSTRAP_RETRY_DELAYS_MS = [ 250, 500 ];
31
-
32
- async function waitForBootstrapRetry( delayMs: number ): Promise< void > {
33
- await new Promise( ( resolve ) => {
34
- setTimeout( resolve, delayMs );
35
- } );
36
- }
37
-
38
- function getClientState(
39
- context: {{pascalCase}}Context
40
- ): {{pascalCase}}ClientState {
41
- if ( context.client ) {
42
- return context.client;
43
- }
44
-
45
- context.client = {
46
- bootstrapError: '',
47
- writeExpiry: 0,
48
- writeNonce: '',
49
- writeToken: '',
50
- };
51
-
52
- return context.client;
53
- }
54
-
55
- function clearBootstrapError(
56
- context: {{pascalCase}}Context,
57
- clientState: {{pascalCase}}ClientState
58
- ): void {
59
- if ( context.error === clientState.bootstrapError ) {
60
- context.error = '';
61
- }
62
- clientState.bootstrapError = '';
63
- }
64
-
65
- function setBootstrapError(
66
- context: {{pascalCase}}Context,
67
- clientState: {{pascalCase}}ClientState,
68
- message: string
69
- ): void {
70
- clientState.bootstrapError = message;
71
- context.error = message;
72
- }
73
-
74
- const { actions, state } = store( '{{slugKebabCase}}', {
75
- state: {
76
- isHydrated: false,
77
- } as {{pascalCase}}State,
78
-
79
- actions: {
80
- async loadState() {
81
- const context = getContext< {{pascalCase}}Context >();
82
- if ( context.postId <= 0 || ! context.resourceKey ) {
83
- return;
84
- }
85
-
86
- context.isLoading = true;
87
- context.error = '';
88
-
89
- try {
90
- const result = await fetchState( {
91
- postId: context.postId,
92
- resourceKey: context.resourceKey,
93
- }, {
94
- transportTarget: 'frontend',
95
- } );
96
- if ( ! result.isValid || ! result.data ) {
97
- context.error = result.errors[ 0 ]?.expected ?? 'Unable to load counter';
98
- return;
99
- }
100
- context.count = result.data.count;
101
- } catch ( error ) {
102
- context.error =
103
- error instanceof Error ? error.message : 'Unknown loading error';
104
- } finally {
105
- context.isLoading = false;
106
- }
107
- },
108
- async loadBootstrap() {
109
- const context = getContext< {{pascalCase}}Context >();
110
- const clientState = getClientState( context );
111
- if ( context.postId <= 0 || ! context.resourceKey ) {
112
- context.bootstrapReady = true;
113
- context.canWrite = false;
114
- clientState.bootstrapError = '';
115
- clientState.writeExpiry = 0;
116
- clientState.writeNonce = '';
117
- clientState.writeToken = '';
118
- return;
119
- }
120
-
121
- context.isBootstrapping = true;
122
-
123
- let bootstrapSucceeded = false;
124
- let lastBootstrapError =
125
- 'Unable to initialize write access';
126
- const includePublicWriteCredentials = {{isPublicPersistencePolicy}};
127
- const includeRestNonce = {{isAuthenticatedPersistencePolicy}};
128
-
129
- for ( let attempt = 1; attempt <= BOOTSTRAP_MAX_ATTEMPTS; attempt += 1 ) {
130
- try {
131
- const result = await fetchBootstrap( {
132
- postId: context.postId,
133
- resourceKey: context.resourceKey,
134
- }, {
135
- transportTarget: 'frontend',
136
- } );
137
- if ( ! result.isValid || ! result.data ) {
138
- lastBootstrapError =
139
- result.errors[ 0 ]?.expected ??
140
- 'Unable to initialize write access';
141
- if ( attempt < BOOTSTRAP_MAX_ATTEMPTS ) {
142
- await waitForBootstrapRetry(
143
- BOOTSTRAP_RETRY_DELAYS_MS[ attempt - 1 ] ?? 750
144
- );
145
- continue;
146
- }
147
- break;
148
- }
149
-
150
- clientState.writeExpiry =
151
- includePublicWriteCredentials &&
152
- 'publicWriteExpiresAt' in result.data &&
153
- typeof result.data.publicWriteExpiresAt === 'number' &&
154
- result.data.publicWriteExpiresAt > 0
155
- ? result.data.publicWriteExpiresAt
156
- : 0;
157
- clientState.writeToken =
158
- includePublicWriteCredentials &&
159
- 'publicWriteToken' in result.data &&
160
- typeof result.data.publicWriteToken === 'string' &&
161
- result.data.publicWriteToken.length > 0
162
- ? result.data.publicWriteToken
163
- : '';
164
- clientState.writeNonce =
165
- includeRestNonce &&
166
- 'restNonce' in result.data &&
167
- typeof result.data.restNonce === 'string' &&
168
- result.data.restNonce.length > 0
169
- ? result.data.restNonce
170
- : '';
171
- context.bootstrapReady = true;
172
- context.canWrite =
173
- result.data.canWrite === true &&
174
- (
175
- context.persistencePolicy === 'authenticated'
176
- ? clientState.writeNonce.length > 0
177
- : clientState.writeToken.length > 0 &&
178
- ! hasExpiredPublicWriteToken( clientState.writeExpiry )
179
- );
180
- clearBootstrapError( context, clientState );
181
- bootstrapSucceeded = true;
182
- break;
183
- } catch ( error ) {
184
- lastBootstrapError =
185
- error instanceof Error ? error.message : 'Unknown bootstrap error';
186
- if ( attempt < BOOTSTRAP_MAX_ATTEMPTS ) {
187
- await waitForBootstrapRetry(
188
- BOOTSTRAP_RETRY_DELAYS_MS[ attempt - 1 ] ?? 750
189
- );
190
- continue;
191
- }
192
- break;
193
- }
194
- }
195
-
196
- if ( ! bootstrapSucceeded ) {
197
- context.bootstrapReady = false;
198
- context.canWrite = false;
199
- clientState.writeExpiry = 0;
200
- clientState.writeNonce = '';
201
- clientState.writeToken = '';
202
- setBootstrapError( context, clientState, lastBootstrapError );
203
- }
204
- context.isBootstrapping = false;
205
- },
206
- async increment() {
207
- const context = getContext< {{pascalCase}}Context >();
208
- const clientState = getClientState( context );
209
- if ( context.postId <= 0 || ! context.resourceKey ) {
210
- return;
211
- }
212
- if ( ! context.bootstrapReady ) {
213
- await actions.loadBootstrap();
214
- }
215
- if ( ! context.bootstrapReady ) {
216
- context.error = 'Write access is still initializing.';
217
- return;
218
- }
219
- if (
220
- context.persistencePolicy === 'public' &&
221
- hasExpiredPublicWriteToken( clientState.writeExpiry )
222
- ) {
223
- await actions.loadBootstrap();
224
- }
225
- if (
226
- context.persistencePolicy === 'public' &&
227
- hasExpiredPublicWriteToken( clientState.writeExpiry )
228
- ) {
229
- context.canWrite = false;
230
- context.error = getWriteBlockedMessage( context );
231
- return;
232
- }
233
- if ( ! context.canWrite ) {
234
- context.error = getWriteBlockedMessage( context );
235
- return;
236
- }
237
-
238
- context.isSaving = true;
239
- context.error = '';
240
-
241
- try {
242
- const result = await writeState( {
243
- delta: 1,
244
- postId: context.postId,
245
- publicWriteRequestId:
246
- context.persistencePolicy === 'public'
247
- ? generatePublicWriteRequestId()
248
- : undefined,
249
- publicWriteToken:
250
- context.persistencePolicy === 'public' &&
251
- clientState.writeToken.length > 0
252
- ? clientState.writeToken
253
- : undefined,
254
- resourceKey: context.resourceKey,
255
- }, {
256
- restNonce:
257
- clientState.writeNonce.length > 0
258
- ? clientState.writeNonce
259
- : undefined,
260
- transportTarget: 'frontend',
261
- } );
262
- if ( ! result.isValid || ! result.data ) {
263
- context.error = result.errors[ 0 ]?.expected ?? 'Unable to update counter';
264
- return;
265
- }
266
- context.count = result.data.count;
267
- context.storage = result.data.storage;
268
- } catch ( error ) {
269
- context.error =
270
- error instanceof Error ? error.message : 'Unknown update error';
271
- } finally {
272
- context.isSaving = false;
273
- }
274
- },
275
- },
276
-
277
- callbacks: {
278
- init() {
279
- const context = getContext< {{pascalCase}}Context >();
280
- context.client = {
281
- bootstrapError: '',
282
- writeExpiry: 0,
283
- writeNonce: '',
284
- writeToken: '',
285
- };
286
- context.bootstrapReady = false;
287
- context.canWrite = false;
288
- context.count = 0;
289
- context.error = '';
290
- context.isBootstrapping = false;
291
- context.isLoading = false;
292
- context.isSaving = false;
293
- },
294
- mounted() {
295
- state.isHydrated = true;
296
- if ( typeof document !== 'undefined' ) {
297
- document.documentElement.dataset[ '{{slugCamelCase}}Hydrated' ] = 'true';
298
- }
299
- void Promise.allSettled( [
300
- actions.loadState(),
301
- actions.loadBootstrap(),
302
- ] );
303
- },
304
- },
305
- } );
@@ -1,152 +0,0 @@
1
- <?php
2
- /**
3
- * Dynamic render entry for the {{title}} compound parent block.
4
- *
5
- * @package {{pascalCase}}
6
- */
7
-
8
- if ( ! defined( 'ABSPATH' ) ) {
9
- exit;
10
- }
11
-
12
- $validator_path = __DIR__ . '/typia-validator.php';
13
- if ( ! file_exists( $validator_path ) ) {
14
- return '';
15
- }
16
-
17
- $validator = require $validator_path;
18
- if ( ! is_object( $validator ) || ! method_exists( $validator, 'apply_defaults' ) || ! method_exists( $validator, 'validate' ) ) {
19
- return '';
20
- }
21
-
22
- $normalized = $validator->apply_defaults( is_array( $attributes ) ? $attributes : array() );
23
- $validation = $validator->validate( $normalized );
24
- $resource_key = isset( $normalized['resourceKey'] ) ? (string) $normalized['resourceKey'] : '';
25
- $heading = isset( $normalized['heading'] ) ? (string) $normalized['heading'] : '{{title}}';
26
- $intro = isset( $normalized['intro'] ) ? (string) $normalized['intro'] : '';
27
- $button_label = isset( $normalized['buttonLabel'] ) ? (string) $normalized['buttonLabel'] : 'Persist Count';
28
- $show_count = ! empty( $normalized['showCount'] );
29
- $show_dividers = ! empty( $normalized['showDividers'] );
30
- $post_id = is_object( $block ) && isset( $block->context['postId'] )
31
- ? (int) $block->context['postId']
32
- : (int) get_queried_object_id();
33
- $storage_mode = '{{dataStorageMode}}';
34
- $persistence_policy = '{{persistencePolicy}}';
35
-
36
- {{phpPrefix}}_record_rendered_block_instance(
37
- (int) $post_id,
38
- '{{namespace}}/{{slugKebabCase}}',
39
- $resource_key
40
- );
41
-
42
- $notice_message = 'authenticated' === $persistence_policy
43
- ? __( 'Sign in to persist this counter.', '{{textDomain}}' )
44
- : __( 'Public writes are temporarily unavailable.', '{{textDomain}}' );
45
-
46
- if ( empty( $validation['valid'] ) || '' === $resource_key ) {
47
- return '';
48
- }
49
-
50
- $context = array(
51
- 'bootstrapReady' => false,
52
- 'buttonLabel' => $button_label,
53
- 'canWrite' => false,
54
- 'client' => array(
55
- 'writeExpiry' => 0,
56
- 'writeNonce' => '',
57
- 'writeToken' => '',
58
- ),
59
- 'count' => 0,
60
- 'error' => '',
61
- 'isBootstrapping' => false,
62
- 'isLoading' => false,
63
- 'isSaving' => false,
64
- 'persistencePolicy' => $persistence_policy,
65
- 'postId' => (int) $post_id,
66
- 'resourceKey' => $resource_key,
67
- 'showCount' => $show_count,
68
- 'storage' => $storage_mode,
69
- );
70
-
71
- $allowed_inner_html = wp_kses_allowed_html( 'post' );
72
-
73
- foreach ( $allowed_inner_html as &$allowed_attributes ) {
74
- if ( ! is_array( $allowed_attributes ) ) {
75
- continue;
76
- }
77
-
78
- $allowed_attributes['data-wp-bind--disabled'] = true;
79
- $allowed_attributes['data-wp-bind--hidden'] = true;
80
- $allowed_attributes['data-wp-bind--value'] = true;
81
- $allowed_attributes['data-wp-class'] = true;
82
- $allowed_attributes['data-wp-class--active'] = true;
83
- $allowed_attributes['data-wp-context'] = true;
84
- $allowed_attributes['data-wp-init'] = true;
85
- $allowed_attributes['data-wp-interactive'] = true;
86
- $allowed_attributes['data-wp-on--click'] = true;
87
- $allowed_attributes['data-wp-on--mouseenter'] = true;
88
- $allowed_attributes['data-wp-on--mouseleave'] = true;
89
- $allowed_attributes['data-wp-run--mounted'] = true;
90
- $allowed_attributes['data-wp-style--width'] = true;
91
- $allowed_attributes['data-wp-text'] = true;
92
- }
93
- unset( $allowed_attributes );
94
-
95
- $sanitized_content = wp_kses( $content, $allowed_inner_html );
96
-
97
- $wrapper_attributes = get_block_wrapper_attributes(
98
- array(
99
- 'class' => '{{cssClassName}}',
100
- 'data-show-dividers' => $show_dividers ? 'true' : 'false',
101
- 'data-wp-context' => wp_json_encode( $context ),
102
- 'data-wp-init' => 'callbacks.init',
103
- 'data-wp-interactive' => '{{slugKebabCase}}',
104
- 'data-wp-run--mounted' => 'callbacks.mounted',
105
- )
106
- );
107
- ?>
108
-
109
- <div <?php echo $wrapper_attributes; ?>>
110
- <h3 class="{{cssClassName}}__heading"><?php echo esc_html( $heading ); ?></h3>
111
- <?php if ( '' !== $intro ) : ?>
112
- <p class="{{cssClassName}}__intro"><?php echo esc_html( $intro ); ?></p>
113
- <?php endif; ?>
114
- <p
115
- class="{{cssClassName}}__notice"
116
- data-wp-bind--hidden="!context.bootstrapReady || context.canWrite"
117
- hidden
118
- >
119
- <?php echo esc_html( $notice_message ); ?>
120
- </p>
121
- <p
122
- class="{{cssClassName}}__error"
123
- role="status"
124
- aria-live="polite"
125
- aria-atomic="true"
126
- data-wp-bind--hidden="!context.error"
127
- data-wp-text="context.error"
128
- hidden
129
- ></p>
130
- <?php if ( $show_count ) : ?>
131
- <div class="{{cssClassName}}__counter">
132
- <span
133
- class="{{cssClassName}}__count"
134
- role="status"
135
- aria-live="polite"
136
- aria-atomic="true"
137
- data-wp-text="context.count"
138
- >0</span>
139
- <button
140
- type="button"
141
- disabled
142
- data-wp-bind--disabled="!context.canWrite"
143
- data-wp-on--click="actions.increment"
144
- >
145
- <?php echo esc_html( $button_label ); ?>
146
- </button>
147
- </div>
148
- <?php endif; ?>
149
- <div class="{{cssClassName}}__items">
150
- <?php echo $sanitized_content; ?>
151
- </div>
152
- </div>
@@ -1,3 +0,0 @@
1
- export default function Save() {
2
- return null;
3
- }
@@ -1,61 +0,0 @@
1
- import type {
2
- TypiaValidationError,
3
- ValidationResult,
4
- } from '@wp-typia/block-runtime/validation';
5
- import { tags } from 'typia';
6
-
7
- export type {
8
- TypiaValidationError,
9
- ValidationResult,
10
- } from '@wp-typia/block-runtime/validation';
11
-
12
- export interface {{pascalCase}}Attributes {
13
- heading: string &
14
- tags.MinLength< 1 > &
15
- tags.MaxLength< 80 > &
16
- tags.Default< {{titleJson}} >;
17
- intro?: string &
18
- tags.MinLength< 1 > &
19
- tags.MaxLength< 180 > &
20
- tags.Default< 'Add and reorder internal items inside this compound block.' >;
21
- showDividers?: boolean & tags.Default< true >;
22
- showCount?: boolean & tags.Default< true >;
23
- buttonLabel?: string &
24
- tags.MinLength< 1 > &
25
- tags.MaxLength< 40 > &
26
- tags.Default< 'Persist Count' >;
27
- resourceKey?: string &
28
- tags.MinLength< 1 > &
29
- tags.MaxLength< 100 > &
30
- tags.Default< 'primary' >;
31
- }
32
-
33
- export interface {{pascalCase}}Context {
34
- buttonLabel: string;
35
- bootstrapReady: boolean;
36
- canWrite: boolean;
37
- count: number;
38
- error: string;
39
- isBootstrapping: boolean;
40
- isLoading: boolean;
41
- isSaving: boolean;
42
- persistencePolicy: 'authenticated' | 'public';
43
- postId: number;
44
- resourceKey: string;
45
- showCount: boolean;
46
- storage: 'post-meta' | 'custom-table';
47
- client?: {{pascalCase}}ClientState;
48
- }
49
-
50
- export interface {{pascalCase}}State {
51
- isHydrated: boolean;
52
- }
53
-
54
- export interface {{pascalCase}}ClientState {
55
- bootstrapError: string;
56
- writeExpiry: number;
57
- writeNonce: string;
58
- writeToken: string;
59
- }
60
-
61
- export type {{pascalCase}}ValidationResult = ValidationResult< {{pascalCase}}Attributes >;
@@ -1,43 +0,0 @@
1
- import typia from 'typia';
2
- import currentManifest from './typia.manifest.json';
3
- import type {
4
- {{pascalCase}}Attributes,
5
- {{pascalCase}}ValidationResult,
6
- } from './types';
7
- import { generateResourceKey } from '@wp-typia/block-runtime/identifiers';
8
- import { createTemplateValidatorToolkit } from '../../validator-toolkit';
9
-
10
- const scaffoldValidators = createTemplateValidatorToolkit< {{pascalCase}}Attributes >( {
11
- assert: typia.createAssert< {{pascalCase}}Attributes >(),
12
- clone: typia.misc.createClone< {{pascalCase}}Attributes >() as (
13
- value: {{pascalCase}}Attributes,
14
- ) => {{pascalCase}}Attributes,
15
- is: typia.createIs< {{pascalCase}}Attributes >(),
16
- manifest: currentManifest,
17
- prune: typia.misc.createPrune< {{pascalCase}}Attributes >(),
18
- random: typia.createRandom< {{pascalCase}}Attributes >() as (
19
- ...args: unknown[]
20
- ) => {{pascalCase}}Attributes,
21
- finalize: ( normalized ) => ( {
22
- ...normalized,
23
- resourceKey:
24
- normalized.resourceKey && normalized.resourceKey.length > 0
25
- ? normalized.resourceKey
26
- : generateResourceKey( '{{slugKebabCase}}' ),
27
- } ),
28
- validate: typia.createValidate< {{pascalCase}}Attributes >(),
29
- } );
30
-
31
- export const validators = scaffoldValidators.validators;
32
-
33
- export const validate{{pascalCase}}Attributes =
34
- scaffoldValidators.validateAttributes as (
35
- attributes: unknown
36
- ) => {{pascalCase}}ValidationResult;
37
-
38
- export const sanitize{{pascalCase}}Attributes =
39
- scaffoldValidators.sanitizeAttributes as (
40
- attributes: Partial< {{pascalCase}}Attributes >
41
- ) => {{pascalCase}}Attributes;
42
-
43
- export const createAttributeUpdater = scaffoldValidators.createAttributeUpdater;