@nextbridgehq/payload-block-builder 0.1.7 → 0.1.9

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.
package/dist/index.cjs CHANGED
@@ -157,18 +157,36 @@ function dbLayoutField(fieldName = "dbLayout", tabLabel = "DB Layout") {
157
157
  },
158
158
  fields: [
159
159
  {
160
- name: "blockDefinition",
161
- type: "relationship",
162
- relationTo: "block-definitions",
163
- required: true,
164
- admin: { description: "Which block type to use." }
165
- },
166
- {
167
- name: "blockVersion",
168
- type: "relationship",
169
- relationTo: "block-definition-versions",
170
- required: true,
171
- admin: { description: "Which schema version to use." }
160
+ type: "row",
161
+ fields: [
162
+ {
163
+ name: "blockDefinition",
164
+ type: "relationship",
165
+ relationTo: "block-definitions",
166
+ required: true,
167
+ admin: {
168
+ description: "Which block type to use.",
169
+ width: "50%",
170
+ components: {
171
+ afterInput: ["@nextbridgehq/payload-block-builder/client#BlockVersionSync"]
172
+ }
173
+ }
174
+ },
175
+ {
176
+ name: "blockVersion",
177
+ type: "relationship",
178
+ relationTo: "block-definition-versions",
179
+ required: true,
180
+ filterOptions: ({ siblingData }) => {
181
+ const def = siblingData?.blockDefinition;
182
+ if (!def) return false;
183
+ const defId = def && typeof def === "object" ? def.id : def;
184
+ if (!defId) return false;
185
+ return { blockDefinition: { equals: defId } };
186
+ },
187
+ admin: { description: "Which schema version to use.", width: "50%" }
188
+ }
189
+ ]
172
190
  },
173
191
  {
174
192
  name: "instanceId",
@@ -360,7 +378,15 @@ var generateEndpoint = async (req) => {
360
378
  var import_uuid = require("uuid");
361
379
  var REVERSE_TYPE_MAP = {
362
380
  richtext: "richText",
363
- image: "upload"
381
+ image: "upload",
382
+ file: "upload",
383
+ // file and image both map to upload in the builder
384
+ multiselect: "select",
385
+ // builder has no multiselect — nearest equivalent
386
+ url: "text",
387
+ // builder has no url field — falls back to text
388
+ color: "text"
389
+ // builder has no color field — falls back to text
364
390
  };
365
391
  var VALID_BUILDER_TYPES = /* @__PURE__ */ new Set([
366
392
  "text",
@@ -387,7 +413,11 @@ var VALID_BUILDER_TYPES = /* @__PURE__ */ new Set([
387
413
  function fieldToBuilderField(raw) {
388
414
  const rawType = String(raw.type ?? "text");
389
415
  const mappedType = REVERSE_TYPE_MAP[rawType] ?? rawType;
390
- const fieldType = VALID_BUILDER_TYPES.has(mappedType) ? mappedType : "text";
416
+ const isKnown = VALID_BUILDER_TYPES.has(mappedType);
417
+ if (!isKnown) {
418
+ console.warn(`[block-builder] Unknown field type "${rawType}" \u2014 rendering as "text". Add a mapping in REVERSE_TYPE_MAP.`);
419
+ }
420
+ const fieldType = isKnown ? mappedType : "text";
391
421
  const field = {
392
422
  id: (0, import_uuid.v4)(),
393
423
  type: fieldType,
@@ -424,7 +454,7 @@ function fieldToBuilderField(raw) {
424
454
  function slugToInterfaceName(slug) {
425
455
  return slug.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
426
456
  }
427
- function schemaToBuilderBlock(slug, name, labels, schemaFields) {
457
+ function schemaToBuilderBlock(slug, _name, labels, schemaFields) {
428
458
  return {
429
459
  id: (0, import_uuid.v4)(),
430
460
  slug,
package/dist/index.js CHANGED
@@ -129,18 +129,36 @@ function dbLayoutField(fieldName = "dbLayout", tabLabel = "DB Layout") {
129
129
  },
130
130
  fields: [
131
131
  {
132
- name: "blockDefinition",
133
- type: "relationship",
134
- relationTo: "block-definitions",
135
- required: true,
136
- admin: { description: "Which block type to use." }
137
- },
138
- {
139
- name: "blockVersion",
140
- type: "relationship",
141
- relationTo: "block-definition-versions",
142
- required: true,
143
- admin: { description: "Which schema version to use." }
132
+ type: "row",
133
+ fields: [
134
+ {
135
+ name: "blockDefinition",
136
+ type: "relationship",
137
+ relationTo: "block-definitions",
138
+ required: true,
139
+ admin: {
140
+ description: "Which block type to use.",
141
+ width: "50%",
142
+ components: {
143
+ afterInput: ["@nextbridgehq/payload-block-builder/client#BlockVersionSync"]
144
+ }
145
+ }
146
+ },
147
+ {
148
+ name: "blockVersion",
149
+ type: "relationship",
150
+ relationTo: "block-definition-versions",
151
+ required: true,
152
+ filterOptions: ({ siblingData }) => {
153
+ const def = siblingData?.blockDefinition;
154
+ if (!def) return false;
155
+ const defId = def && typeof def === "object" ? def.id : def;
156
+ if (!defId) return false;
157
+ return { blockDefinition: { equals: defId } };
158
+ },
159
+ admin: { description: "Which schema version to use.", width: "50%" }
160
+ }
161
+ ]
144
162
  },
145
163
  {
146
164
  name: "instanceId",
@@ -332,7 +350,15 @@ var generateEndpoint = async (req) => {
332
350
  import { v4 as uuidv4 } from "uuid";
333
351
  var REVERSE_TYPE_MAP = {
334
352
  richtext: "richText",
335
- image: "upload"
353
+ image: "upload",
354
+ file: "upload",
355
+ // file and image both map to upload in the builder
356
+ multiselect: "select",
357
+ // builder has no multiselect — nearest equivalent
358
+ url: "text",
359
+ // builder has no url field — falls back to text
360
+ color: "text"
361
+ // builder has no color field — falls back to text
336
362
  };
337
363
  var VALID_BUILDER_TYPES = /* @__PURE__ */ new Set([
338
364
  "text",
@@ -359,7 +385,11 @@ var VALID_BUILDER_TYPES = /* @__PURE__ */ new Set([
359
385
  function fieldToBuilderField(raw) {
360
386
  const rawType = String(raw.type ?? "text");
361
387
  const mappedType = REVERSE_TYPE_MAP[rawType] ?? rawType;
362
- const fieldType = VALID_BUILDER_TYPES.has(mappedType) ? mappedType : "text";
388
+ const isKnown = VALID_BUILDER_TYPES.has(mappedType);
389
+ if (!isKnown) {
390
+ console.warn(`[block-builder] Unknown field type "${rawType}" \u2014 rendering as "text". Add a mapping in REVERSE_TYPE_MAP.`);
391
+ }
392
+ const fieldType = isKnown ? mappedType : "text";
363
393
  const field = {
364
394
  id: uuidv4(),
365
395
  type: fieldType,
@@ -396,7 +426,7 @@ function fieldToBuilderField(raw) {
396
426
  function slugToInterfaceName(slug) {
397
427
  return slug.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
398
428
  }
399
- function schemaToBuilderBlock(slug, name, labels, schemaFields) {
429
+ function schemaToBuilderBlock(slug, _name, labels, schemaFields) {
400
430
  return {
401
431
  id: uuidv4(),
402
432
  slug,
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@nextbridgehq/payload-block-builder",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Block Builder for Payload CMS",
5
- "keywords": ["payload", "payload-plugin", "cms", "block-builder", "dynamic-blocks"],
5
+ "keywords": ["payload", "payloadcms", "payload-plugin", "cms", "block-builder", "dynamic-blocks"],
6
6
  "homepage": "https://github.com/nextbridgehq/block-builder",
7
7
  "repository": {
8
8
  "type": "git",
@@ -362,6 +362,176 @@
362
362
 
363
363
  /* ── States ──────────────────────────────────────────────────────────────── */
364
364
 
365
+ /* Relationship Picker */
366
+
367
+ .bdf-rel {
368
+ display: flex;
369
+ width: 100%;
370
+ }
371
+
372
+ .bdf-rel__control {
373
+ flex: 1;
374
+ display: flex;
375
+ align-items: center;
376
+ min-height: 40px;
377
+ padding: 4px 8px;
378
+ background: var(--theme-input-bg, var(--theme-elevation-0));
379
+ border: 1px solid var(--theme-elevation-150);
380
+ border-radius: var(--style-radius-s, 4px);
381
+ cursor: pointer;
382
+ transition: border-color 0.1s;
383
+ box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.1);
384
+ box-sizing: border-box;
385
+ user-select: none;
386
+ }
387
+ .bdf-rel__control:hover {
388
+ border-color: var(--theme-elevation-250);
389
+ }
390
+ .bdf-rel__control:focus {
391
+ outline: none;
392
+ border-color: var(--theme-elevation-400);
393
+ }
394
+
395
+ .bdf-rel--multi .bdf-rel__control {
396
+ border-top-right-radius: 0;
397
+ border-bottom-right-radius: 0;
398
+ border-right: none;
399
+ }
400
+
401
+ .bdf-rel__values {
402
+ flex: 1;
403
+ display: flex;
404
+ flex-wrap: wrap;
405
+ align-items: center;
406
+ gap: 4px;
407
+ min-width: 0;
408
+ padding: 2px 0;
409
+ }
410
+
411
+ .bdf-rel__placeholder {
412
+ color: var(--theme-elevation-400);
413
+ font-size: 1rem;
414
+ font-family: var(--font-body);
415
+ }
416
+
417
+ .bdf-rel__single {
418
+ font-size: 1rem;
419
+ color: var(--theme-elevation-800);
420
+ font-family: var(--font-body);
421
+ overflow: hidden;
422
+ text-overflow: ellipsis;
423
+ white-space: nowrap;
424
+ }
425
+
426
+ .bdf-rel__chip {
427
+ display: inline-flex;
428
+ align-items: stretch;
429
+ background: var(--theme-elevation-100);
430
+ border: 1px solid var(--theme-elevation-200);
431
+ border-radius: var(--style-radius-s, 4px);
432
+ font-size: 13px;
433
+ font-family: var(--font-body);
434
+ color: var(--theme-elevation-800);
435
+ max-width: 200px;
436
+ overflow: hidden;
437
+ }
438
+
439
+ .bdf-rel__chip-label {
440
+ padding: 2px 6px;
441
+ overflow: hidden;
442
+ text-overflow: ellipsis;
443
+ white-space: nowrap;
444
+ }
445
+
446
+ .bdf-rel__chip-remove {
447
+ display: flex;
448
+ align-items: center;
449
+ justify-content: center;
450
+ padding: 0 5px;
451
+ background: transparent;
452
+ border: none;
453
+ border-left: 1px solid var(--theme-elevation-200);
454
+ cursor: pointer;
455
+ color: var(--theme-elevation-500);
456
+ flex-shrink: 0;
457
+ line-height: 1;
458
+ transition: background 0.1s, color 0.1s;
459
+ }
460
+ .bdf-rel__chip-remove:hover {
461
+ background: var(--theme-elevation-150);
462
+ color: var(--theme-elevation-900);
463
+ }
464
+
465
+ .bdf-rel__indicators {
466
+ display: flex;
467
+ align-items: center;
468
+ padding-left: 4px;
469
+ flex-shrink: 0;
470
+ gap: 2px;
471
+ }
472
+
473
+ .bdf-rel__clear {
474
+ display: flex;
475
+ align-items: center;
476
+ justify-content: center;
477
+ width: 24px;
478
+ height: 24px;
479
+ background: transparent;
480
+ border: none;
481
+ cursor: pointer;
482
+ color: var(--theme-elevation-400);
483
+ padding: 0;
484
+ border-radius: 50%;
485
+ transition: color 0.1s;
486
+ }
487
+ .bdf-rel__clear:hover {
488
+ color: var(--theme-elevation-800);
489
+ }
490
+
491
+ .bdf-rel__sep {
492
+ display: block;
493
+ width: 1px;
494
+ height: 18px;
495
+ background: var(--theme-elevation-200);
496
+ margin: 0 4px;
497
+ }
498
+
499
+ .bdf-rel__chevron {
500
+ display: flex;
501
+ align-items: center;
502
+ color: var(--theme-elevation-400);
503
+ }
504
+
505
+ .bdf-rel__add {
506
+ display: flex;
507
+ align-items: center;
508
+ justify-content: center;
509
+ min-height: 40px;
510
+ padding: 0 14px;
511
+ background: var(--theme-elevation-100);
512
+ border: 1px solid var(--theme-elevation-150);
513
+ border-radius: 0 var(--style-radius-s, 4px) var(--style-radius-s, 4px) 0;
514
+ cursor: pointer;
515
+ color: var(--theme-elevation-700);
516
+ font-size: 20px;
517
+ font-family: var(--font-body);
518
+ line-height: 1;
519
+ transition: background 0.1s;
520
+ white-space: nowrap;
521
+ box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.1);
522
+ box-sizing: border-box;
523
+ }
524
+ .bdf-rel__add:hover {
525
+ background: var(--theme-elevation-150);
526
+ }
527
+
528
+ .bdf-rel__hint {
529
+ margin-top: 4px;
530
+ font-size: 12px;
531
+ color: var(--theme-elevation-500);
532
+ font-family: var(--font-body);
533
+ }
534
+
365
535
  .bdf-empty {
366
536
  padding: calc(var(--base, 16px) * 1.5) var(--base, 16px);
367
537
  border: 1px dashed var(--theme-elevation-200);