@times-design-system/components-wordpress 1.2.1 → 1.2.2-alpha.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 (51) hide show
  1. package/BLOCK_CREATION_CHECKLIST.md +39 -16
  2. package/README.md +4 -4
  3. package/TRANSFORMATION_GUIDE.md +3 -3
  4. package/block.json +1 -1
  5. package/dist/block.json +1 -1
  6. package/dist/blocks/ad-container/block.json +2 -1
  7. package/dist/blocks/ad-container/render.php +27 -0
  8. package/dist/blocks/button/block.json +2 -1
  9. package/dist/blocks/button/render.php +71 -0
  10. package/dist/blocks/chip/block.json +2 -1
  11. package/dist/blocks/chip/render.php +40 -0
  12. package/dist/blocks/divider/block.json +2 -1
  13. package/dist/blocks/divider/render.php +31 -0
  14. package/dist/blocks/flag/block.json +2 -1
  15. package/dist/blocks/flag/render.php +34 -0
  16. package/dist/blocks/icon-button/block.json +2 -1
  17. package/dist/blocks/icon-button/render.php +46 -0
  18. package/dist/blocks/input/block.json +2 -1
  19. package/dist/blocks/input/render.php +39 -0
  20. package/dist/blocks/link/block.json +2 -1
  21. package/dist/blocks/link/render.php +44 -0
  22. package/dist/blocks/text/block.json +2 -1
  23. package/dist/blocks/text/render.php +26 -0
  24. package/dist/blocks/toast/block.json +2 -1
  25. package/dist/blocks/toast/render.php +37 -0
  26. package/dist/index.cjs +30 -10
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.js +30 -10
  29. package/dist/index.js.map +1 -1
  30. package/package.json +3 -3
  31. package/scripts/create-block.sh +1 -1
  32. package/src/blocks/ad-container/block.json +2 -1
  33. package/src/blocks/ad-container/render.php +27 -0
  34. package/src/blocks/button/block.json +2 -1
  35. package/src/blocks/button/render.php +71 -0
  36. package/src/blocks/chip/block.json +2 -1
  37. package/src/blocks/chip/render.php +40 -0
  38. package/src/blocks/divider/block.json +2 -1
  39. package/src/blocks/divider/render.php +31 -0
  40. package/src/blocks/flag/block.json +2 -1
  41. package/src/blocks/flag/render.php +34 -0
  42. package/src/blocks/icon-button/block.json +2 -1
  43. package/src/blocks/icon-button/render.php +46 -0
  44. package/src/blocks/input/block.json +2 -1
  45. package/src/blocks/input/render.php +39 -0
  46. package/src/blocks/link/block.json +2 -1
  47. package/src/blocks/link/render.php +44 -0
  48. package/src/blocks/text/block.json +2 -1
  49. package/src/blocks/text/render.php +26 -0
  50. package/src/blocks/toast/block.json +2 -1
  51. package/src/blocks/toast/render.php +37 -0
@@ -16,14 +16,16 @@ Use this checklist when creating each new WordPress block from a React component
16
16
  - [ ] Created `block.json` manifest
17
17
  - [ ] Created `index.js` registration file
18
18
  - [ ] Created `edit.js` editor component
19
- - [ ] Created `save.js` frontend component
19
+ - [ ] Created `save.js` frontend component (static output only, no event handlers)
20
+ - [ ] Created `render.php` server-side rendering callback
20
21
  - [ ] Created `style.css` frontend styles
21
22
  - [ ] Created `style-editor.css` (if needed)
22
23
 
23
24
  ## 3. block.json
24
25
 
25
- - [ ] Set `name` to `times/<component-name>`
26
+ - [ ] Set `name` to `tds/<component-name>`
26
27
  - [ ] Set descriptive `title`
28
+ - [ ] Added `"render": "file:./render.php"` for server-side rendering
27
29
  - [ ] Added all React props as `attributes`
28
30
  - [ ] Set appropriate `type` for each attribute
29
31
  - [ ] Added `enum` arrays for variant props
@@ -45,10 +47,25 @@ Use this checklist when creating each new WordPress block from a React component
45
47
 
46
48
  ## 5. save.js
47
49
 
48
- - [ ] Used `useBlockProps.save()`
49
- - [ ] Returned valid, deterministic HTML
50
- - [ ] Output matches React component structure
51
- - [ ] No event handlers or dynamic behavior
50
+ - [ ] Used `useBlockProps.save()` (no event handlers or state)
51
+ - [ ] Output structure matches what `render.php` outputs
52
+ - [ ] No dynamic behavior or client-side logic
53
+ - [ ] Included proper ARIA attributes
54
+
55
+ ## 5b. render.php
56
+
57
+ - [ ] Created PHP file that mirrors `save.js` output
58
+ - [ ] Used `sanitize_*()` and `esc_*()` functions for all attributes
59
+ - [ ] Used `get_block_wrapper_attributes()` for wrapper
60
+ - [ ] Used `wp_kses_post()` for any rich content
61
+ - [ ] Conditionally rendered elements based on attributes
62
+ - [ ] Added proper PHPDoc header with @package taghavior
63
+
64
+ ## 6b. Pattern Testing
65
+
66
+ - [ ] Verified block renders in patterns (server-side rendering)
67
+ - [ ] Tested block with various attribute combinations in patterns
68
+ - [ ] Confirmed HTML output in pattern matches `render.php` structure
52
69
  - [ ] Included proper ARIA attributes
53
70
 
54
71
  ## 6. Styling
@@ -111,15 +128,21 @@ Track which components have been transformed:
111
128
 
112
129
  ## Quick Reference: Prop Type → Block Attribute
113
130
 
114
- ```
115
- React Type → Block.json Type & Example
131
+ Issue: Block doesn't render in patterns
132
+
133
+ **Solution**: Verify `render.php` exists and is referenced in `block.json` with `"render": "file:./render.php"`. Render callbacks provide server-side rendering for patterns.
134
+
135
+ ### Issue: Block appears but styles are missing in patterns
136
+
137
+ **Solution**: Ensure theme/plugin enqueues block CSS with `wp_enqueue_style()` on both frontend and editor
116
138
  ─────────────────────────────────────────────────
117
- string → "type": "string", "default": ""
118
- boolean → "type": "boolean", "default": false
119
- enum (union) → "enum": ["a", "b"], "default": "a"
120
- number → "type": "number", "default": 0
121
- Event handler → Not supported (use editor preview only)
122
- ```
139
+ string → "type": "string", "default": ""
140
+ boolean → "type": "boolean", "default": false
141
+ enum (union) → "enum": ["a", "b"], "default": "a"
142
+ number → "type": "number", "default": 0
143
+ Event handler → Not supported (use editor preview only)
144
+
145
+ ````
123
146
 
124
147
  ---
125
148
 
@@ -127,7 +150,7 @@ Event handler → Not supported (use editor preview only)
127
150
 
128
151
  ### Issue: Block doesn't appear in inserter
129
152
 
130
- **Solution**: Verify `block.json` has `name: "times/..."` and `index.js` imports block registration
153
+ **Solution**: Verify `block.json` has `name: "tds/..."` and `index.js` imports block registration
131
154
 
132
155
  ### Issue: Attributes not persisting
133
156
 
@@ -157,4 +180,4 @@ npm run build
157
180
 
158
181
  # Validate JSON
159
182
  npm run test
160
- ```
183
+ ````
package/README.md CHANGED
@@ -633,7 +633,7 @@ addFilter(
633
633
  'blocks.registerBlockType',
634
634
  'my-plugin/modify-button',
635
635
  (settings, name) => {
636
- if (name === 'times/button') {
636
+ if (name === 'tds/button') {
637
637
  // Add custom attribute
638
638
  settings.attributes.myCustomAttr = {
639
639
  type: 'string',
@@ -653,7 +653,7 @@ addFilter(
653
653
 
654
654
  function register_times_block_styles() {
655
655
  register_block_style(
656
- 'times/button',
656
+ 'tds/button',
657
657
  [
658
658
  'name' => 'gradient',
659
659
  'label' => 'Gradient Style',
@@ -707,13 +707,13 @@ Create reusable block patterns:
707
707
  <?php
708
708
  // In your plugin/theme
709
709
  register_block_pattern(
710
- 'times/hero-with-button',
710
+ 'tds/hero-with-button',
711
711
  [
712
712
  'title' => 'Hero Section with Button',
713
713
  'description' => 'Large hero section with Times Design System button',
714
714
  'content' => '
715
715
  <!-- wp:cover {"url":"...","minHeight":400} -->
716
- <!-- wp:times/button {"label":"Learn More","intent":"primary","size":"large"} /-->
716
+ <!-- wp:tds/button {"label":"Learn More","intent":"primary","size":"large"} /-->
717
717
  <!-- /wp:cover -->
718
718
  ',
719
719
  'categories' => [ 'hero' ],
@@ -89,7 +89,7 @@ mkdir -p packages/components-wordpress/src/blocks/<component-name>
89
89
  {
90
90
  "$schema": "https://schemas.wp.org/trunk/block.json",
91
91
  "apiVersion": 3,
92
- "name": "times/<block-name>",
92
+ "name": "tds/<block-name>",
93
93
  "title": "Block Display Name",
94
94
  "category": "common",
95
95
  "description": "Brief description",
@@ -131,7 +131,7 @@ mkdir -p packages/components-wordpress/src/blocks/<component-name>
131
131
  ```json
132
132
  {
133
133
  "apiVersion": 3,
134
- "name": "times/button",
134
+ "name": "tds/button",
135
135
  "title": "Button",
136
136
  "attributes": {
137
137
  "label": {
@@ -597,7 +597,7 @@ Suggested order for consistent, dependency-aware transformation:
597
597
 
598
598
  ### Block not appearing in Gutenberg?
599
599
 
600
- 1. Check `block.json` has `name: "times/..."`
600
+ 1. Check `block.json` has `name: "tds/..."`
601
601
  2. Verify `edit.js` and `save.js` are exported as default
602
602
  3. Check console for JavaScript errors
603
603
  4. Rebuild: `npm run build`
package/block.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
- "name": "times/design-system-blocks",
4
+ "name": "tds/design-system-blocks",
5
5
  "title": "Times Design System Blocks",
6
6
  "category": "times-design-system",
7
7
  "description": "A collection of Gutenberg blocks built with Times Design System components",
package/dist/block.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
- "name": "times/design-system-blocks",
4
+ "name": "tds/design-system-blocks",
5
5
  "title": "Times Design System Blocks",
6
6
  "category": "times-design-system",
7
7
  "description": "A collection of Gutenberg blocks built with Times Design System components",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
- "name": "times/ad-container",
4
+ "name": "tds/ad-container",
5
5
  "title": "Ad Container",
6
6
  "category": "common",
7
7
  "description": "Advertising container placeholder",
@@ -13,6 +13,7 @@
13
13
  "padding": true
14
14
  }
15
15
  },
16
+ "render": "file:./render.php",
16
17
  "attributes": {
17
18
  "type": {
18
19
  "type": "string",
@@ -0,0 +1,27 @@
1
+ <?php
2
+ /**
3
+ * Ad Container Block Render Callback
4
+ *
5
+ * Renders the Ad Container block on the frontend.
6
+ *
7
+ * @package TimesDesignSystem\ComponentsWordPress
8
+ * @var array $attributes Block attributes
9
+ * @var string $content Block content
10
+ * @var WP_Block $block Block instance
11
+ */
12
+
13
+ $type = isset($attributes['type']) ? sanitize_text_field($attributes['type']) : '';
14
+ $slot_id = isset($attributes['slotID']) ? sanitize_text_field($attributes['slotID']) : '';
15
+
16
+ $class_name = 'tds-ad-container';
17
+ if ($type) {
18
+ $class_name .= ' tds-ad-container--' . sanitize_html_class($type);
19
+ }
20
+
21
+ $wrapper_attrs = get_block_wrapper_attributes(['class' => $class_name]);
22
+ ?>
23
+
24
+ <div
25
+ <?php echo wp_kses_post($wrapper_attrs); ?>
26
+ <?php echo $slot_id ? 'data-slot-id="' . esc_attr($slot_id) . '"' : ''; ?>
27
+ ></div>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
- "name": "times/button",
4
+ "name": "tds/button",
5
5
  "title": "Button",
6
6
  "category": "common",
7
7
  "description": "A customizable button component for user interactions",
@@ -16,6 +16,7 @@
16
16
  "customClassName": true
17
17
  },
18
18
  "textdomain": "times-design-system",
19
+ "render": "file:./render.php",
19
20
  "attributes": {
20
21
  "label": {
21
22
  "type": "string",
@@ -0,0 +1,71 @@
1
+ <?php
2
+ /**
3
+ * Button Block Render Callback
4
+ *
5
+ * Renders the Button block on the frontend.
6
+ *
7
+ * @package TimesDesignSystem\ComponentsWordPress
8
+ * @var array $attributes Block attributes
9
+ * @var string $content Block content
10
+ * @var WP_Block $block Block instance
11
+ */
12
+
13
+ $label = isset($attributes['label']) ? sanitize_text_field($attributes['label']) : 'Button label';
14
+ $intent = isset($attributes['intent']) ? sanitize_text_field($attributes['intent']) : 'primary';
15
+ $size = isset($attributes['size']) ? sanitize_text_field($attributes['size']) : 'large';
16
+ $behaviour = isset($attributes['behaviour']) ? sanitize_text_field($attributes['behaviour']) : 'hug';
17
+ $state = isset($attributes['state']) ? sanitize_text_field($attributes['state']) : 'base';
18
+ $disabled = isset($attributes['disabled']) ? (bool) $attributes['disabled'] : false;
19
+ $href = isset($attributes['href']) ? esc_url($attributes['href']) : '';
20
+ $target = isset($attributes['target']) ? sanitize_text_field($attributes['target']) : '';
21
+ $rel = isset($attributes['rel']) ? sanitize_text_field($attributes['rel']) : '';
22
+ $type = isset($attributes['type']) ? sanitize_text_field($attributes['type']) : 'button';
23
+ $aria_label = isset($attributes['ariaLabel']) ? sanitize_text_field($attributes['ariaLabel']) : '';
24
+
25
+ // Build button classes
26
+ $classes = ['tds-button'];
27
+ $classes[] = 'tds-button--intent-' . $intent;
28
+ $classes[] = 'tds-button--size-' . $size;
29
+ $classes[] = 'tds-button--behaviour-' . $behaviour;
30
+ $classes[] = 'tds-button--state-' . $state;
31
+ if ($disabled) {
32
+ $classes[] = 'tds-button--disabled';
33
+ }
34
+
35
+ $button_class = implode(' ', $classes);
36
+ $element_tag = $href ? 'a' : 'button';
37
+ $wrapper_attrs = get_block_wrapper_attributes(['class' => 'tds-button-wrapper']);
38
+ ?>
39
+
40
+ <div <?php echo wp_kses_post($wrapper_attrs); ?>>
41
+ <?php
42
+ if ($element_tag === 'a') {
43
+ ?>
44
+ <a
45
+ class="<?php echo esc_attr($button_class); ?>"
46
+ href="<?php echo esc_attr($href); ?>"
47
+ <?php echo $target ? 'target="' . esc_attr($target) . '"' : ''; ?>
48
+ <?php echo $rel ? 'rel="' . esc_attr($rel) . '"' : ''; ?>
49
+ <?php echo $aria_label ? 'aria-label="' . esc_attr($aria_label) . '"' : ''; ?>
50
+ >
51
+ <span class="tds-button__label-container">
52
+ <span class="tds-button__label"><?php echo wp_kses_post($label); ?></span>
53
+ </span>
54
+ </a>
55
+ <?php
56
+ } else {
57
+ ?>
58
+ <button
59
+ class="<?php echo esc_attr($button_class); ?>"
60
+ <?php echo $disabled ? 'disabled' : ''; ?>
61
+ type="<?php echo esc_attr($type); ?>"
62
+ <?php echo $aria_label ? 'aria-label="' . esc_attr($aria_label) . '"' : ''; ?>
63
+ >
64
+ <span class="tds-button__label-container">
65
+ <span class="tds-button__label"><?php echo wp_kses_post($label); ?></span>
66
+ </span>
67
+ </button>
68
+ <?php
69
+ }
70
+ ?>
71
+ </div>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
- "name": "times/chip",
4
+ "name": "tds/chip",
5
5
  "title": "Chip",
6
6
  "category": "common",
7
7
  "description": "Small component for displaying labels, tags, or filter options",
@@ -12,6 +12,7 @@
12
12
  "margin": true
13
13
  }
14
14
  },
15
+ "render": "file:./render.php",
15
16
  "attributes": {
16
17
  "content": {
17
18
  "type": "string",
@@ -0,0 +1,40 @@
1
+ <?php
2
+ /**
3
+ * Chip Block Render Callback
4
+ *
5
+ * Renders the Chip block on the frontend.
6
+ *
7
+ * @package TimesDesignSystem\ComponentsWordPress
8
+ * @var array $attributes Block attributes
9
+ * @var string $content Block content
10
+ * @var WP_Block $block Block instance
11
+ */
12
+
13
+ $content_text = isset($attributes['content']) ? wp_kses_post($attributes['content']) : '';
14
+ $intent = isset($attributes['intent']) ? sanitize_text_field($attributes['intent']) : '';
15
+ $size = isset($attributes['size']) ? sanitize_text_field($attributes['size']) : '';
16
+ $state = isset($attributes['state']) ? sanitize_text_field($attributes['state']) : '';
17
+ $channel = isset($attributes['channel']) ? (bool) $attributes['channel'] : false;
18
+ $toggle = isset($attributes['toggle']) ? (bool) $attributes['toggle'] : false;
19
+ $aria_label = isset($attributes['ariaLabel']) ? sanitize_text_field($attributes['ariaLabel']) : '';
20
+
21
+ $classes = ['tds-chip'];
22
+ $classes[] = 'tds-chip--intent-' . $intent;
23
+ $classes[] = 'tds-chip--size-' . $size;
24
+ $classes[] = 'tds-chip--state-' . $state;
25
+ if ($channel) {
26
+ $classes[] = 'tds-chip--channel';
27
+ }
28
+ if ($toggle) {
29
+ $classes[] = 'tds-chip--toggle';
30
+ }
31
+
32
+ $wrapper_attrs = get_block_wrapper_attributes(['class' => implode(' ', $classes)]);
33
+ ?>
34
+
35
+ <button
36
+ <?php echo wp_kses_post($wrapper_attrs); ?>
37
+ <?php echo $aria_label ? 'aria-label="' . esc_attr($aria_label) . '"' : ''; ?>
38
+ >
39
+ <span class="tds-chip__content"><?php echo wp_kses_post($content_text); ?></span>
40
+ </button>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
- "name": "times/divider",
4
+ "name": "tds/divider",
5
5
  "title": "Divider",
6
6
  "category": "common",
7
7
  "description": "A horizontal line divider component",
@@ -13,6 +13,7 @@
13
13
  },
14
14
  "align": ["wide", "full"]
15
15
  },
16
+ "render": "file:./render.php",
16
17
  "attributes": {
17
18
  "isDashed": {
18
19
  "type": "boolean",
@@ -0,0 +1,31 @@
1
+ <?php
2
+ /**
3
+ * Divider Block Render Callback
4
+ *
5
+ * Renders the Divider block on the frontend.
6
+ *
7
+ * @package TimesDesignSystem\ComponentsWordPress
8
+ * @var array $attributes Block attributes
9
+ * @var string $content Block content
10
+ * @var WP_Block $block Block instance
11
+ */
12
+
13
+ $is_dashed = isset($attributes['isDashed']) ? (bool) $attributes['isDashed'] : false;
14
+ $is_vertical = isset($attributes['isVertical']) ? (bool) $attributes['isVertical'] : false;
15
+ $padding = isset($attributes['padding']) ? (bool) $attributes['padding'] : false;
16
+
17
+ $classes = ['tds-divider'];
18
+ if ($is_dashed) {
19
+ $classes[] = 'tds-divider--dashed';
20
+ }
21
+ if ($is_vertical) {
22
+ $classes[] = 'tds-divider--vertical';
23
+ }
24
+ if ($padding) {
25
+ $classes[] = 'tds-divider--padding';
26
+ }
27
+
28
+ $wrapper_attrs = get_block_wrapper_attributes(['class' => implode(' ', $classes)]);
29
+ ?>
30
+
31
+ <div <?php echo wp_kses_post($wrapper_attrs); ?>></div>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
- "name": "times/flag",
4
+ "name": "tds/flag",
5
5
  "title": "Flag",
6
6
  "category": "common",
7
7
  "description": "Badge or status indicator component",
@@ -12,6 +12,7 @@
12
12
  "margin": true
13
13
  }
14
14
  },
15
+ "render": "file:./render.php",
15
16
  "attributes": {
16
17
  "label": {
17
18
  "type": "string",
@@ -0,0 +1,34 @@
1
+ <?php
2
+ /**
3
+ * Flag Block Render Callback
4
+ *
5
+ * Renders the Flag block on the frontend.
6
+ *
7
+ * @package TimesDesignSystem\ComponentsWordPress
8
+ * @var array $attributes Block attributes
9
+ * @var string $content Block content
10
+ * @var WP_Block $block Block instance
11
+ */
12
+
13
+ $label = isset($attributes['label']) ? sanitize_text_field($attributes['label']) : '';
14
+ $content_text = isset($attributes['content']) ? wp_kses_post($attributes['content']) : '';
15
+ $intent = isset($attributes['intent']) ? sanitize_text_field($attributes['intent']) : '';
16
+ $size = isset($attributes['size']) ? sanitize_text_field($attributes['size']) : '';
17
+ $aria_label = isset($attributes['ariaLabel']) ? sanitize_text_field($attributes['ariaLabel']) : '';
18
+
19
+ $classes = ['tds-flag'];
20
+ $classes[] = 'tds-flag--intent-' . $intent;
21
+ $classes[] = 'tds-flag--size-' . $size;
22
+
23
+ $wrapper_attrs = get_block_wrapper_attributes(['class' => implode(' ', $classes)]);
24
+ ?>
25
+
26
+ <div
27
+ <?php echo wp_kses_post($wrapper_attrs); ?>
28
+ <?php echo $aria_label ? 'aria-label="' . esc_attr($aria_label) . '"' : ''; ?>
29
+ >
30
+ <?php if ($label) : ?>
31
+ <div class="tds-flag__label"><?php echo wp_kses_post($label); ?></div>
32
+ <?php endif; ?>
33
+ <div class="tds-flag__content"><?php echo wp_kses_post($content_text); ?></div>
34
+ </div>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
- "name": "times/icon-button",
4
+ "name": "tds/icon-button",
5
5
  "title": "Icon Button",
6
6
  "category": "common",
7
7
  "description": "Button component displaying only an icon",
@@ -12,6 +12,7 @@
12
12
  "margin": true
13
13
  }
14
14
  },
15
+ "render": "file:./render.php",
15
16
  "attributes": {
16
17
  "iconName": {
17
18
  "type": "string",
@@ -0,0 +1,46 @@
1
+ <?php
2
+ /**
3
+ * Icon Button Block Render Callback
4
+ *
5
+ * Renders the Icon Button block on the frontend.
6
+ *
7
+ * @package TimesDesignSystem\ComponentsWordPress
8
+ * @var array $attributes Block attributes
9
+ * @var string $content Block content
10
+ * @var WP_Block $block Block instance
11
+ */
12
+
13
+ $icon_name = isset($attributes['iconName']) ? sanitize_text_field($attributes['iconName']) : '';
14
+ $round = isset($attributes['round']) ? (bool) $attributes['round'] : false;
15
+ $href = isset($attributes['href']) ? esc_url($attributes['href']) : '';
16
+ $target = isset($attributes['target']) ? sanitize_text_field($attributes['target']) : '';
17
+ $rel = isset($attributes['rel']) ? sanitize_text_field($attributes['rel']) : '';
18
+ $aria_label = isset($attributes['ariaLabel']) ? sanitize_text_field($attributes['ariaLabel']) : '';
19
+
20
+ $classes = ['tds-icon-button'];
21
+ if ($round) {
22
+ $classes[] = 'tds-icon-button--round';
23
+ }
24
+
25
+ $element_tag = $href ? 'a' : 'button';
26
+ $wrapper_attrs = get_block_wrapper_attributes(['class' => implode(' ', $classes)]);
27
+ ?>
28
+
29
+ <?php if ($element_tag === 'a') : ?>
30
+ <a
31
+ <?php echo wp_kses_post($wrapper_attrs); ?>
32
+ href="<?php echo esc_attr($href); ?>"
33
+ <?php echo $target ? 'target="' . esc_attr($target) . '"' : ''; ?>
34
+ <?php echo $rel ? 'rel="' . esc_attr($rel) . '"' : ''; ?>
35
+ <?php echo $aria_label ? 'aria-label="' . esc_attr($aria_label) . '"' : ''; ?>
36
+ >
37
+ <span class="tds-icon-button__icon"><?php echo wp_kses_post($icon_name); ?></span>
38
+ </a>
39
+ <?php else : ?>
40
+ <button
41
+ <?php echo wp_kses_post($wrapper_attrs); ?>
42
+ <?php echo $aria_label ? 'aria-label="' . esc_attr($aria_label) . '"' : ''; ?>
43
+ >
44
+ <span class="tds-icon-button__icon"><?php echo wp_kses_post($icon_name); ?></span>
45
+ </button>
46
+ <?php endif; ?>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
- "name": "times/input",
4
+ "name": "tds/input",
5
5
  "title": "Input",
6
6
  "category": "common",
7
7
  "description": "Form input field component",
@@ -12,6 +12,7 @@
12
12
  "margin": true
13
13
  }
14
14
  },
15
+ "render": "file:./render.php",
15
16
  "attributes": {
16
17
  "label": {
17
18
  "type": "string",
@@ -0,0 +1,39 @@
1
+ <?php
2
+ /**
3
+ * Input Block Render Callback
4
+ *
5
+ * Renders the Input block on the frontend.
6
+ *
7
+ * @package TimesDesignSystem\ComponentsWordPress
8
+ * @var array $attributes Block attributes
9
+ * @var string $content Block content
10
+ * @var WP_Block $block Block instance
11
+ */
12
+
13
+ $label = isset($attributes['label']) ? sanitize_text_field($attributes['label']) : '';
14
+ $placeholder = isset($attributes['placeholder']) ? sanitize_text_field($attributes['placeholder']) : '';
15
+ $type = isset($attributes['type']) ? sanitize_text_field($attributes['type']) : 'text';
16
+ $disabled = isset($attributes['disabled']) ? (bool) $attributes['disabled'] : false;
17
+ $required = isset($attributes['required']) ? (bool) $attributes['required'] : false;
18
+ $name = isset($attributes['name']) ? sanitize_text_field($attributes['name']) : '';
19
+ $id = isset($attributes['id']) ? sanitize_text_field($attributes['id']) : '';
20
+
21
+ $wrapper_attrs = get_block_wrapper_attributes();
22
+ ?>
23
+
24
+ <div <?php echo wp_kses_post($wrapper_attrs); ?>>
25
+ <?php if ($label) : ?>
26
+ <label for="<?php echo esc_attr($id); ?>" class="tds-input__label">
27
+ <?php echo wp_kses_post($label); ?>
28
+ </label>
29
+ <?php endif; ?>
30
+ <input
31
+ type="<?php echo esc_attr($type); ?>"
32
+ <?php echo $placeholder ? 'placeholder="' . esc_attr($placeholder) . '"' : ''; ?>
33
+ <?php echo $disabled ? 'disabled' : ''; ?>
34
+ <?php echo $required ? 'required' : ''; ?>
35
+ <?php echo $name ? 'name="' . esc_attr($name) . '"' : ''; ?>
36
+ <?php echo $id ? 'id="' . esc_attr($id) . '"' : ''; ?>
37
+ class="tds-input"
38
+ />
39
+ </div>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
- "name": "times/link",
4
+ "name": "tds/link",
5
5
  "title": "Link",
6
6
  "category": "common",
7
7
  "description": "Styled link component with variants and states",
@@ -12,6 +12,7 @@
12
12
  "margin": true
13
13
  }
14
14
  },
15
+ "render": "file:./render.php",
15
16
  "attributes": {
16
17
  "href": {
17
18
  "type": "string",
@@ -0,0 +1,44 @@
1
+ <?php
2
+ /**
3
+ * Link Block Render Callback
4
+ *
5
+ * Renders the Link block on the frontend.
6
+ *
7
+ * @package TimesDesignSystem\ComponentsWordPress
8
+ * @var array $attributes Block attributes
9
+ * @var string $content Block content
10
+ * @var WP_Block $block Block instance
11
+ */
12
+
13
+ $href = isset($attributes['href']) ? esc_url($attributes['href']) : '';
14
+ $content_text = isset($attributes['content']) ? wp_kses_post($attributes['content']) : '';
15
+ $intent = isset($attributes['intent']) ? sanitize_text_field($attributes['intent']) : '';
16
+ $sentiment = isset($attributes['sentiment']) ? sanitize_text_field($attributes['sentiment']) : '';
17
+ $size = isset($attributes['size']) ? sanitize_text_field($attributes['size']) : '';
18
+ $state = isset($attributes['state']) ? sanitize_text_field($attributes['state']) : '';
19
+ $inline = isset($attributes['inline']) ? (bool) $attributes['inline'] : true;
20
+ $aria_label = isset($attributes['ariaLabel']) ? sanitize_text_field($attributes['ariaLabel']) : '';
21
+ $target = isset($attributes['target']) ? sanitize_text_field($attributes['target']) : '_self';
22
+ $rel = isset($attributes['rel']) ? sanitize_text_field($attributes['rel']) : '';
23
+
24
+ $classes = ['tds-link'];
25
+ $classes[] = 'tds-link--intent-' . $intent;
26
+ $classes[] = 'tds-link--sentiment-' . $sentiment;
27
+ $classes[] = 'tds-link--size-' . $size;
28
+ $classes[] = 'tds-link--state-' . $state;
29
+ if (!$inline) {
30
+ $classes[] = 'tds-link--block';
31
+ }
32
+
33
+ $wrapper_attrs = get_block_wrapper_attributes(['class' => implode(' ', $classes)]);
34
+ ?>
35
+
36
+ <a
37
+ <?php echo wp_kses_post($wrapper_attrs); ?>
38
+ href="<?php echo esc_attr($href); ?>"
39
+ <?php echo $aria_label ? 'aria-label="' . esc_attr($aria_label) . '"' : ''; ?>
40
+ <?php echo ($target !== '_self') ? 'target="' . esc_attr($target) . '"' : ''; ?>
41
+ <?php echo $rel ? 'rel="' . esc_attr($rel) . '"' : ''; ?>
42
+ >
43
+ <span class="tds-link__content"><?php echo wp_kses_post($content_text); ?></span>
44
+ </a>