prisma-php 0.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.
@@ -0,0 +1,589 @@
1
+ ---
2
+ title: Prisma PHP Components for AI Awareness
3
+ description: Learn how AI agents should understand, locate, import, and generate Prisma PHP components using the official PHPX and ImportComponent patterns.
4
+ related:
5
+ title: Related docs
6
+ description: Read the official Prisma PHP component docs before generating or editing components.
7
+ links:
8
+ - /docs/get-started-phpx
9
+ - /docs/import-component
10
+ - /docs/fragment
11
+ - /docs/icon-component
12
+ - /docs/button-component
13
+ - /docs/accordion-component
14
+ ---
15
+
16
+ Prisma PHP components should be generated using the official **PHPX** and **ImportComponent** models, not assumptions from React, Vue, Blade components, or generic PHP templating.
17
+
18
+ If a task involves component creation, component editing, component composition, PHPX rendering rules, or importing PHP partials as PulsePoint-ready islands, AI agents should read the relevant local Prisma PHP docs first and use the installed framework conventions before generating code.
19
+
20
+ ## AI rule: read the component docs first
21
+
22
+ Before generating, editing, or reviewing components, use this order:
23
+
24
+ 1. Read `./prisma-php.json`.
25
+ 2. Read the installed local docs in `node_modules/prisma-php/dist/docs`.
26
+ 3. Inspect the existing local component structure.
27
+ 4. Inspect Prisma PHP core internals only when the docs do not answer the task.
28
+
29
+ Do not assume JSX, TSX, Blade, Vue SFC, React, or generic PHP partial behavior applies directly.
30
+
31
+ ## Read this doc when you need
32
+
33
+ - **PHPX component basics, naming, file placement, props, children, or reactive props** → `get-started-phpx`
34
+ - **importing a PHP partial as a component, component islands, `ImportComponent::render(...)`, or server-first PulsePoint boundaries** → `import-component`
35
+ - **multiple sibling nodes, wrapperless output, or `<>...</>` usage** → `fragment`
36
+ - **custom SVG icon components** → `icon-component`
37
+ - **button component structure, variants, sizes, or theme-aware classes** → `button-component`
38
+ - **accordion components, grouped sub-components, `StateManager`, or injected JS lifecycle rules** → `accordion-component`
39
+
40
+ ## Two component models AI must not confuse
41
+
42
+ Prisma PHP has **two related but different component models**.
43
+
44
+ ### 1. PHPX class-based components
45
+
46
+ Use this model when building reusable PHP component classes such as:
47
+
48
+ - `Button`
49
+ - `Accordion`
50
+ - `Search`
51
+ - `Card`
52
+ - `Icon`
53
+
54
+ These components:
55
+
56
+ - extend the PHPX base class
57
+ - usually live in a component namespace such as `src/app/Lib/Components`
58
+ - render HTML from `render(): string`
59
+ - use class-based props and helpers such as `$this->children`, `$this->class`, and `$this->getAttributes(...)`
60
+
61
+ ### 2. `ImportComponent` partial-based components
62
+
63
+ Use this model when a plain PHP file or partial should become a **real PulsePoint component boundary**.
64
+
65
+ This is the right mental model for:
66
+
67
+ - server-first pages with small reactive islands
68
+ - imported PHP partials that must receive props as HTML attributes
69
+ - componentized partials that PulsePoint should hydrate later
70
+ - keeping PHP templating ergonomics while still producing component-aware markup
71
+
72
+ AI must not collapse these two models into one.
73
+
74
+ - **PHPX** is for class-based component authoring.
75
+ - **`ImportComponent`** is for importing PHP partial files as single-root component islands.
76
+
77
+ ## Important AI rules for Prisma PHP components
78
+
79
+ - treat the official Prisma PHP component docs as the source of truth
80
+ - use **PHPX** for class-based reusable components
81
+ - use **`ImportComponent`** when a PHP partial should become a PulsePoint-ready component boundary
82
+ - keep file names and class names aligned for PHPX class components
83
+ - prefer the documented component directories and naming patterns
84
+ - do not invent undocumented lifecycle hooks, props APIs, or import behavior
85
+ - preserve Prisma PHP XML-style markup rules when returning component markup
86
+ - use `$this->children`, `$this->props`, `$this->class`, and `$this->getAttributes(...)` following the documented PHPX pattern
87
+ - when a component needs reactivity, distinguish between static PHP props and reactive PulsePoint props
88
+ - when a component requires grouped sub-components, follow the documented same-file naming pattern like `Accordion`, `AccordionItem`, `AccordionTrigger`, and `AccordionContent`
89
+ - when using `ImportComponent`, always ensure the imported file renders **exactly one root element**
90
+
91
+ ## Component file placement and naming
92
+
93
+ The official PHPX docs describe a file and naming convention centered on class-based components.
94
+
95
+ A standard component should usually live in a component-oriented path such as:
96
+
97
+ ```txt
98
+ src/app/Lib/Components/Button.php
99
+ ```
100
+
101
+ The class name should match the file name.
102
+
103
+ Examples:
104
+
105
+ - `Button.php` → `class Button`
106
+ - `Search.php` → `class Search`
107
+ - `Accordion.php` → `class Accordion`
108
+
109
+ ### Related component naming
110
+
111
+ When a component is made of multiple related sub-components, the official docs recommend keeping them grouped under the same naming family.
112
+
113
+ Example naming group:
114
+
115
+ - `Accordion`
116
+ - `AccordionItem`
117
+ - `AccordionTrigger`
118
+ - `AccordionContent`
119
+
120
+ These related classes can live in the same file, and each class name should begin with the shared main component prefix.
121
+
122
+ Example path:
123
+
124
+ ```txt
125
+ src/app/Lib/PHPX/Components/Accordion.php
126
+ ```
127
+
128
+ ### Imported partial component paths
129
+
130
+ For `ImportComponent`, the input is a **PHP file path**, not a PHPX class reference.
131
+
132
+ Common examples:
133
+
134
+ ```txt
135
+ APP_PATH . '/inc/Hero.php'
136
+ APP_PATH . '/inc/SearchBox.php'
137
+ APP_PATH . '/components/UserCard.php'
138
+ ```
139
+
140
+ AI should preserve the project's actual partial locations instead of inventing a new component folder structure when the task is specifically about imported partials.
141
+
142
+ ## Base PHPX component shape
143
+
144
+ A Prisma PHPX component should generally:
145
+
146
+ 1. extend the PHPX base class
147
+ 2. accept `array $props = []` in the constructor
148
+ 3. call `parent::__construct($props)`
149
+ 4. render a string from `render(): string`
150
+ 5. use helper methods such as `getMergeClasses(...)` and `getAttributes(...)` when appropriate
151
+
152
+ Typical shape:
153
+
154
+ ```php
155
+ <?php
156
+
157
+ namespace Lib\Components;
158
+
159
+ use Lib\PHPX\PHPX;
160
+
161
+ class ClassName extends PHPX
162
+ {
163
+ public ?string $class = '';
164
+ public mixed $children = null;
165
+
166
+ public function __construct(array $props = [])
167
+ {
168
+ parent::__construct($props);
169
+ }
170
+
171
+ public function render(): string
172
+ {
173
+ $class = $this->getMergeClasses($this->class);
174
+ $attributes = $this->getAttributes([
175
+ 'class' => $class,
176
+ ]);
177
+
178
+ return <<<HTML
179
+ <div {$attributes}>
180
+ {$this->children}
181
+ </div>
182
+ HTML;
183
+ }
184
+ }
185
+ ```
186
+
187
+ ## Core PHPX props model
188
+
189
+ The official PHPX docs describe these important component properties:
190
+
191
+ - `$props` → all incoming props and attributes
192
+ - `$children` → inner rendered content
193
+ - `$class` → CSS class input for styling
194
+ - `$attributesArray` → HTML attributes prepared for rendering
195
+
196
+ AI should not invent alternative prop containers when the PHPX base model already provides these.
197
+
198
+ ## Static props vs reactive props
199
+
200
+ Prisma PHP components separate normal server-side props from reactive PulsePoint props.
201
+
202
+ ### Static props
203
+
204
+ Static props are plain PHP values and should be treated as normal typed component inputs.
205
+
206
+ Examples:
207
+
208
+ ```xml
209
+ <Button type="submit" class="w-full" />
210
+ <TestComponent isChildren="true" />
211
+ ```
212
+
213
+ ### Reactive props
214
+
215
+ Reactive PulsePoint props must use mustache syntax.
216
+
217
+ Examples:
218
+
219
+ ```xml
220
+ <TestComponent counter="{count}" setCounter="{setCount}" />
221
+ ```
222
+
223
+ ### AI rule for reactive props
224
+
225
+ - use normal quoted props for static PHP values
226
+ - use mustache syntax for PulsePoint signals and client-reactive values
227
+ - do not mix the two models casually
228
+ - when a child component must receive browser-side state, pass it in mustache form
229
+
230
+ ## `ImportComponent` rules
231
+
232
+ The official `ImportComponent` docs describe it as the utility that turns a PHP partial into a real PulsePoint component boundary.
233
+
234
+ ### What `ImportComponent` does
235
+
236
+ When you call:
237
+
238
+ ```php
239
+ ImportComponent::render($filePath, $props);
240
+ ```
241
+
242
+ Prisma PHP:
243
+
244
+ 1. executes the component file in an isolated namespace
245
+ 2. captures the produced HTML output
246
+ 3. parses it as an XML fragment
247
+ 4. enforces exactly one root element
248
+ 5. injects a stable `pp-component` attribute
249
+ 6. serializes props into HTML attributes on the root element
250
+ 7. stores a snapshot accessible through `ImportComponent::sections()`
251
+
252
+ ### AI rules for `ImportComponent`
253
+
254
+ - use `ImportComponent` for PHP partials, not for PHPX class components
255
+ - require exactly one root element in the imported file
256
+ - treat the imported output as a PulsePoint-ready island boundary
257
+ - pass server data as props and let Prisma PHP serialize them into attributes
258
+ - use mustache-valued props when passing reactive PulsePoint bindings into imported partials
259
+ - do not assume multiple top-level siblings are allowed
260
+ - do not manually inject `pp-component`; let `ImportComponent` do it
261
+
262
+ ### Basic usage
263
+
264
+ ```php
265
+ <?php
266
+
267
+ use PP\ImportComponent;
268
+
269
+ ImportComponent::render(APP_PATH . '/inc/Hero.php');
270
+ ```
271
+
272
+ ### Passing props
273
+
274
+ ```php
275
+ <?php
276
+
277
+ use PP\ImportComponent;
278
+
279
+ $user = ['id' => 7, 'name' => 'Jefferson'];
280
+
281
+ ImportComponent::render(APP_PATH . '/inc/UserCard.php', [
282
+ 'user' => $user,
283
+ 'variant' => 'compact',
284
+ 'isOnline' => true,
285
+ ]);
286
+ ```
287
+
288
+ ### Reactive PulsePoint bindings
289
+
290
+ ```php
291
+ <?php
292
+
293
+ use PP\ImportComponent;
294
+ ?>
295
+
296
+ <div class="space-y-4">
297
+ <?php ImportComponent::render(APP_PATH . '/inc/SearchBox.php', [
298
+ 'query' => '{query}',
299
+ 'setQuery' => '{setQuery}',
300
+ ]); ?>
301
+
302
+ <script type="text/pp">
303
+ const [query, setQuery] = pp.state('');
304
+ </script>
305
+ </div>
306
+ ```
307
+
308
+ ### Imported file requirements
309
+
310
+ The imported PHP file must output **exactly one root element**.
311
+
312
+ Correct:
313
+
314
+ ```php
315
+ <div class="rounded-lg border bg-card p-4">
316
+ <h2 class="font-medium">Search</h2>
317
+ <input value="{query}" oninput="{(e) => setQuery(e.target.value)}" />
318
+ </div>
319
+ ```
320
+
321
+ Incorrect:
322
+
323
+ ```php
324
+ <h2 class="font-medium">Search</h2>
325
+ <input value="{query}" oninput="{(e) => setQuery(e.target.value)}" />
326
+ ```
327
+
328
+ ## `ImportComponent` prop serialization rules
329
+
330
+ The official docs define these serialization rules:
331
+
332
+ - `null` props are skipped
333
+ - booleans become `"true"` or `"false"`
334
+ - scalar values become strings
335
+ - arrays and objects become JSON
336
+ - when a prop value contains PulsePoint mustache syntax like `{count}`, Prisma PHP converts camelCase prop keys to kebab-case attribute names when needed for HTML-safe output
337
+
338
+ ### AI implications
339
+
340
+ - pass normal PHP arrays and objects directly; do not pre-JSON-encode them manually unless the project already does that intentionally
341
+ - expect reactive props like `setCount` to become an HTML attribute such as `set-count` when the value contains mustache syntax
342
+ - do not rely on camelCase HTML attributes surviving unchanged in mustache-driven import cases
343
+
344
+ ## Exposed functions inside imported components
345
+
346
+ The official `ImportComponent` docs also note an automatic exposed-function registry behavior during isolated execution.
347
+
348
+ That means an imported component file can define an exposed PHP function, and Prisma PHP can register it for later use through the exposed-function tooling.
349
+
350
+ Example:
351
+
352
+ ```php
353
+ <?php
354
+
355
+ use PP\Attributes\Exposed;
356
+
357
+ #[Exposed]
358
+ function saveDraft(array $payload): array
359
+ {
360
+ return ['ok' => true];
361
+ }
362
+ ?>
363
+
364
+ <div class="rounded-md border p-4">
365
+ Draft editor
366
+ </div>
367
+ ```
368
+
369
+ ### AI rule
370
+
371
+ If a component file imported via `ImportComponent` defines `#[Exposed]` functions, do not move them out just because they are inside the imported file. Preserve the documented pattern unless the user explicitly wants a different structure.
372
+
373
+ ## Fragment rules
374
+
375
+ The official `Fragment` component exists so PHPX components can return multiple sibling elements in heredoc output without forcing an unnecessary wrapper element.
376
+
377
+ Use `<Fragment>` or the shorthand fragment syntax:
378
+
379
+ ```php
380
+ return <<<HTML
381
+ <>
382
+ <h1 class="text-2xl font-bold">Heading</h1>
383
+ <p class="text-muted-foreground">Paragraph</p>
384
+ </>
385
+ HTML;
386
+ ```
387
+
388
+ ### When to use `Fragment`
389
+
390
+ Use it when:
391
+
392
+ - a PHPX component must return multiple siblings
393
+ - you want to avoid an unnecessary wrapper `div`
394
+ - semantic HTML would be harmed by adding an extra wrapper
395
+ - you are using heredoc output and PHPX still needs a single parseable root structure
396
+
397
+ ### Important distinction
398
+
399
+ `Fragment` is a **PHPX rendering tool**.
400
+
401
+ It is **not** the same as `ImportComponent`'s single-root partial rule.
402
+
403
+ - in **PHPX**, `Fragment` is how multiple siblings can be represented
404
+ - in **`ImportComponent`**, the imported partial itself must still resolve to exactly one root element
405
+
406
+ AI should not misuse fragment concepts to bypass the `ImportComponent` single-root requirement.
407
+
408
+ ## Icon component rules
409
+
410
+ The official icon component docs recommend SVG as the preferred format for custom icon components because SVG is lightweight, vector-based, and easy to style with utility classes.
411
+
412
+ A manual icon component follows the normal PHPX class pattern.
413
+
414
+ Typical structure:
415
+
416
+ ```php
417
+ <?php
418
+
419
+ namespace Lib\GoogleIcons;
420
+
421
+ use PP\PHPX\PHPX;
422
+
423
+ class Search extends PHPX
424
+ {
425
+ public ?string $class = '';
426
+
427
+ public function __construct(array $props = [])
428
+ {
429
+ parent::__construct($props);
430
+ }
431
+
432
+ public function render(): string
433
+ {
434
+ $class = $this->getMergeClasses($this->class);
435
+ $attributes = $this->getAttributes([
436
+ 'class' => $class,
437
+ ]);
438
+
439
+ return <<<HTML
440
+ <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" {$attributes}>
441
+ <path d="..." />
442
+ </svg>
443
+ HTML;
444
+ }
445
+ }
446
+ ```
447
+
448
+ ### AI rules for icon components
449
+
450
+ - prefer SVG over raster formats when creating reusable icons
451
+ - expose `class` so the icon can be styled from the caller
452
+ - use `fill="currentColor"` when the icon should follow text color
453
+ - keep the component small and focused on rendering the SVG
454
+ - do not hardcode visual styling when utility classes can control it
455
+
456
+ ## Button component rules
457
+
458
+ The official Button component docs present Button as a reusable PHPX component with:
459
+
460
+ - variants
461
+ - sizes
462
+ - theme-aware utility classes
463
+ - support for normal button rendering and anchor-style rendering
464
+
465
+ ### AI rules for button components
466
+
467
+ - place button components in a standard component path such as `src/app/Lib/Components/Button.php`
468
+ - extend the PHPX base class
469
+ - use props like `variant` and `size` from `$this->props`
470
+ - compute classes centrally in a helper such as `getComputedClasses()`
471
+ - prefer theme token utilities like `bg-primary`, `text-primary-foreground`, `bg-destructive`, and `border-input` instead of hardcoded colors
472
+ - preserve accessibility-related states such as focus rings and disabled styles
473
+
474
+ ### Common button structure
475
+
476
+ A documented button pattern typically includes:
477
+
478
+ - base classes for layout, typography, focus, and disabled state
479
+ - a variant map
480
+ - a size map
481
+ - merged user classes from `$class`
482
+ - optional rendering differences when the component should behave like a link
483
+
484
+ ## Accordion component rules
485
+
486
+ The official Accordion docs define Accordion as a grouped PHPX component system with multiple classes working together.
487
+
488
+ ### Related classes
489
+
490
+ - `Accordion`
491
+ - `AccordionItem`
492
+ - `AccordionTrigger`
493
+ - `AccordionContent`
494
+
495
+ ### Important lifecycle rule
496
+
497
+ The docs explicitly note that Prisma PHPX execution starts from the innermost child to the outermost parent. Because of that, the parent `Accordion` constructs last, and that is why the JavaScript is injected there after child IDs are ready.
498
+
499
+ ### AI rules for accordions
500
+
501
+ - keep related accordion classes in the same naming family
502
+ - use `StateManager` when following the documented ID-sharing pattern between trigger and content
503
+ - inject shared accordion JavaScript from the parent component when using the documented lifecycle pattern
504
+ - preserve WAI-ARIA attributes such as `aria-controls`, `aria-expanded`, `aria-labelledby`, and `role="region"`
505
+ - keep default visibility and animation classes in the content container unless the design intentionally changes them
506
+
507
+ ### Sub-component responsibilities
508
+
509
+ - `AccordionItem` wraps a single item pair
510
+ - `AccordionTrigger` renders the clickable control and manages toggle-related IDs
511
+ - `AccordionContent` renders the hidden content region using the shared item ID state
512
+
513
+ ## XML-style syntax rule for component output
514
+
515
+ When AI generates Prisma PHP components, returned markup should follow strict XML-style rules used across Prisma PHP templates.
516
+
517
+ Correct:
518
+
519
+ ```xml
520
+ <hr />
521
+ <input type="text" />
522
+ <Search class="size-4" />
523
+ ```
524
+
525
+ Incorrect:
526
+
527
+ ```xml
528
+ <hr>
529
+ <input type="text">
530
+ <Search class=size-4>
531
+ ```
532
+
533
+ Also:
534
+
535
+ - close all tags properly
536
+ - use double quotes for attributes
537
+ - avoid shorthand boolean attributes
538
+
539
+ ## When AI should inspect framework internals
540
+
541
+ If the installed docs and local project code are not enough, AI may inspect Prisma PHP core internals in:
542
+
543
+ ```txt
544
+ vendor/tsnc/prisma-php/src
545
+ ```
546
+
547
+ Important component-related files may include:
548
+
549
+ - `vendor/tsnc/prisma-php/src/PHPX/PHPX.php`
550
+ - `vendor/tsnc/prisma-php/src/PHPX/Fragment.php`
551
+ - `vendor/tsnc/prisma-php/src/PHPX/TemplateCompiler.php`
552
+ - `vendor/tsnc/prisma-php/src/PHPX/TwMerge.php`
553
+ - `vendor/tsnc/prisma-php/src/PHPX/TypeCoercer.php`
554
+ - `vendor/tsnc/prisma-php/src/ImportComponent.php`
555
+ - `vendor/tsnc/prisma-php/src/StateManager.php`
556
+ - `vendor/tsnc/prisma-php/src/Attributes/Exposed.php`
557
+
558
+ Use these files to verify internals only when necessary. Do not treat vendor internals as the first stop when the installed docs already answer the task.
559
+
560
+ ## Recommended AI workflow for component tasks
561
+
562
+ When asked to create or edit a Prisma PHP component, AI should follow this workflow:
563
+
564
+ 1. Read `prisma-php.json`.
565
+ 2. Read the relevant installed component docs.
566
+ 3. Decide whether the task is **PHPX class-based** or **`ImportComponent` partial-based**.
567
+ 4. Inspect the local component namespace and folder conventions.
568
+ 5. Match file name and class name for PHPX class components.
569
+ 6. Use XML-style markup in `render(): string` or in imported partial output.
570
+ 7. Use static props and reactive props correctly.
571
+ 8. Enforce the single-root rule for `ImportComponent` partials.
572
+ 9. Only inspect `vendor/tsnc/prisma-php/src` when the docs or local usage are not enough.
573
+
574
+ ## Quick component lookup table
575
+
576
+ | Task | Read first | Typical location |
577
+ | ----------------------------------------- | --------------------- | ---------------------------------------------- |
578
+ | create a reusable PHPX component | `get-started-phpx` | `src/app/Lib/Components/ClassName.php` |
579
+ | import a PHP partial as a reactive island | `import-component` | `APP_PATH . '/inc/ComponentName.php'` |
580
+ | return multiple siblings in PHPX | `fragment` | `vendor/tsnc/prisma-php/src/PHPX/Fragment.php` |
581
+ | create an SVG icon component | `icon-component` | `src/app/Lib/GoogleIcons/Search.php` |
582
+ | create a theme-aware button | `button-component` | `src/app/Lib/Components/Button.php` |
583
+ | create a grouped accordion | `accordion-component` | `src/app/Lib/Components/Accordion.php` |
584
+
585
+ ## Final AI reminder
586
+
587
+ For Prisma PHP components, do not guess.
588
+
589
+ Read the official component docs first, decide whether the task belongs to **PHPX** or **`ImportComponent`**, preserve strict XML-style output, and only inspect Prisma PHP core internals when you truly need framework-level implementation details.