create-mendix-widget-gleam 1.1.4 → 2.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.
- package/README.md +6 -3
- package/package.json +1 -1
- package/src/index.mjs +152 -8
- package/template/docs/glendix_guide.md +839 -228
- package/template/gleam.toml +1 -1
- package/template/src/components/hello_world.gleam +2 -2
package/README.md
CHANGED
|
@@ -27,7 +27,10 @@ my-widget/
|
|
|
27
27
|
editor_preview.gleam # Studio Pro 디자인 뷰 미리보기
|
|
28
28
|
components/
|
|
29
29
|
hello_world.gleam # Hello World 공유 컴포넌트
|
|
30
|
-
|
|
30
|
+
widgets/ # .mpk 위젯 파일 (glendix/widget로 바인딩)
|
|
31
|
+
bindings.json # 외부 React 컴포넌트 바인딩 설정
|
|
32
|
+
package.json # npm 의존성 (React, 외부 라이브러리 등)
|
|
33
|
+
gleam.toml # Gleam 프로젝트 설정 (glendix >= 2.0.1 의존성 포함)
|
|
31
34
|
CLAUDE.md # AI 어시스턴트용 프로젝트 컨텍스트
|
|
32
35
|
```
|
|
33
36
|
|
|
@@ -46,8 +49,8 @@ gleam run -m glendix/build # 프로덕션 빌드 (.mpk 생성)
|
|
|
46
49
|
|
|
47
50
|
생성된 프로젝트는 [glendix](https://hexdocs.pm/glendix/) Hex 패키지를 의존성으로 사용한다. glendix가 React 원시 함수와 Mendix Pluggable Widget API 전체에 대한 타입 안전한 Gleam 바인딩을 제공한다:
|
|
48
51
|
|
|
49
|
-
- **React** — `react`, `react/
|
|
50
|
-
- **Mendix** — `mendix`, `mendix/editable_value`, `mendix/action`, `mendix/list_value`, `mendix/selection`, `mendix/reference`, `mendix/date`, `mendix/big`, `mendix/filter` 등
|
|
52
|
+
- **React** — `react`, `react/attribute`, `react/hook`, `react/event`, `react/html`, `react/svg`, `react/svg_attribute`, `binding`, `widget`
|
|
53
|
+
- **Mendix** — `mendix`, `mendix/editable_value`, `mendix/action`, `mendix/list_value`, `mendix/selection`, `mendix/reference`, `mendix/reference_set`, `mendix/date`, `mendix/big`, `mendix/filter` 등
|
|
51
54
|
|
|
52
55
|
## 라이선스
|
|
53
56
|
|
package/package.json
CHANGED
package/src/index.mjs
CHANGED
|
@@ -192,6 +192,9 @@ src/
|
|
|
192
192
|
package.xml # Mendix 패키지 매니페스트
|
|
193
193
|
ui/
|
|
194
194
|
${names.pascalCase}.css # 위젯 스타일시트
|
|
195
|
+
widgets/ # .mpk 위젯 파일 (glendix/widget로 바인딩)
|
|
196
|
+
bindings.json # 외부 React 컴포넌트 바인딩 설정
|
|
197
|
+
package.json # npm 의존성 (React, 외부 라이브러리 등)
|
|
195
198
|
gleam.toml # Gleam 프로젝트 설정 (glendix 의존성 포함)
|
|
196
199
|
docs/
|
|
197
200
|
gleam_language_tour.md # Gleam 언어 레퍼런스
|
|
@@ -231,8 +234,8 @@ gleam format # Gleam 코드 포맷팅
|
|
|
231
234
|
|
|
232
235
|
\`docs/glendix_guide.md\` 파일에 glendix 패키지의 사용법이 수록되어 있다. 주요 내용:
|
|
233
236
|
- 프로젝트 설정 및 첫 번째 위젯 만들기
|
|
234
|
-
- 핵심 개념: opaque 타입, undefined ↔ Option 변환,
|
|
235
|
-
- React 바인딩: 엘리먼트 생성,
|
|
237
|
+
- 핵심 개념: opaque 타입, undefined ↔ Option 변환, Attribute 리스트 API
|
|
238
|
+
- React 바인딩: 엘리먼트 생성, Attribute 리스트, HTML 태그 함수, Hooks, 이벤트 처리, 조건부/리스트 렌더링, 스타일, 외부 React 컴포넌트 바인딩, .mpk 위젯 바인딩
|
|
236
239
|
- Mendix 바인딩: Props 접근, ValueStatus, EditableValue, ActionValue, DynamicValue, ListValue, ListAttribute, Selection, Reference, Filter, JsDate, Big 등
|
|
237
240
|
- 실전 패턴: 폼 입력 위젯, 데이터 테이블, 검색 가능 리스트, 컴포넌트 합성
|
|
238
241
|
- 트러블슈팅
|
|
@@ -240,12 +243,15 @@ gleam format # Gleam 코드 포맷팅
|
|
|
240
243
|
## glendix Modules
|
|
241
244
|
|
|
242
245
|
React:
|
|
243
|
-
- \`glendix/react\` — 핵심 타입 +
|
|
244
|
-
- \`glendix/react/
|
|
245
|
-
- \`glendix/react/hook\` — React Hooks (useState, useEffect 등)
|
|
246
|
-
- \`glendix/react/event\` — 이벤트 타입 +
|
|
247
|
-
- \`glendix/react/html\` — HTML 태그 편의 함수
|
|
246
|
+
- \`glendix/react\` — 핵심 타입 + element/element_/void_element/component_el + fragment/text/none + 조건부 렌더링 + define_component/memo/Context
|
|
247
|
+
- \`glendix/react/attribute\` — Attribute 리스트 API (90+ HTML 속성 함수)
|
|
248
|
+
- \`glendix/react/hook\` — React Hooks (useState, useEffect, useMemo, useCallback, useRef 등)
|
|
249
|
+
- \`glendix/react/event\` — 15개 이벤트 타입 + 148+ 핸들러 Attribute + 67+ 접근자
|
|
250
|
+
- \`glendix/react/html\` — 75+ HTML 태그 편의 함수
|
|
251
|
+
- \`glendix/react/svg\` — 57 SVG 요소 편의 함수
|
|
252
|
+
- \`glendix/react/svg_attribute\` — 97+ SVG 전용 속성 함수
|
|
248
253
|
- \`glendix/binding\` — 외부 React 컴포넌트 바인딩
|
|
254
|
+
- \`glendix/widget\` — .mpk 위젯 컴포넌트 바인딩
|
|
249
255
|
|
|
250
256
|
Mendix:
|
|
251
257
|
- \`glendix/mendix\` — \`ValueStatus\`, \`ObjectItem\`, Props 접근자
|
|
@@ -255,7 +261,8 @@ Mendix:
|
|
|
255
261
|
- \`glendix/mendix/list_value\` — 리스트 데이터 + 정렬/필터
|
|
256
262
|
- \`glendix/mendix/list_attribute\` — 리스트 아이템별 접근
|
|
257
263
|
- \`glendix/mendix/selection\` — 단일/다중 선택
|
|
258
|
-
- \`glendix/mendix/reference\` —
|
|
264
|
+
- \`glendix/mendix/reference\` — 단일 연관 참조
|
|
265
|
+
- \`glendix/mendix/reference_set\` — 다중 연관 참조
|
|
259
266
|
- \`glendix/mendix/date\` — JS Date 래퍼
|
|
260
267
|
- \`glendix/mendix/big\` — Big.js 고정밀 십진수 래퍼
|
|
261
268
|
- \`glendix/mendix/file\` — 파일/이미지
|
|
@@ -288,6 +295,44 @@ async function generateReadme(targetDir, names, pm, pmConfig) {
|
|
|
288
295
|
|
|
289
296
|
Gleam 언어로 작성된 Mendix Pluggable Widget.
|
|
290
297
|
|
|
298
|
+
## 핵심 원리
|
|
299
|
+
|
|
300
|
+
Gleam 함수 \`fn(JsProps) -> ReactElement\`는 React 함수형 컴포넌트와 동일한 시그니처다. glendix가 React 원시 함수와 Mendix 런타임 타입 접근자를 타입 안전하게 제공하므로, 위젯 프로젝트에서는 비즈니스 로직에만 집중하면 된다.
|
|
301
|
+
|
|
302
|
+
\`\`\`gleam
|
|
303
|
+
// src/${names.snakeCase}.gleam
|
|
304
|
+
import glendix/mendix
|
|
305
|
+
import glendix/react.{type JsProps, type ReactElement}
|
|
306
|
+
import glendix/react/attribute
|
|
307
|
+
import glendix/react/html
|
|
308
|
+
|
|
309
|
+
pub fn widget(props: JsProps) -> ReactElement {
|
|
310
|
+
let sample_text = mendix.get_string_prop(props, "sampleText")
|
|
311
|
+
html.div([attribute.class("widget-hello-world")], [
|
|
312
|
+
react.text("Hello " <> sample_text),
|
|
313
|
+
])
|
|
314
|
+
}
|
|
315
|
+
\`\`\`
|
|
316
|
+
|
|
317
|
+
Mendix 복합 타입도 Gleam에서 타입 안전하게 사용할 수 있다:
|
|
318
|
+
|
|
319
|
+
\`\`\`gleam
|
|
320
|
+
import glendix/mendix
|
|
321
|
+
import glendix/mendix/editable_value
|
|
322
|
+
import glendix/mendix/action
|
|
323
|
+
|
|
324
|
+
pub fn widget(props: JsProps) -> ReactElement {
|
|
325
|
+
// EditableValue 접근
|
|
326
|
+
let name_attr: EditableValue = mendix.get_prop_required(props, "name")
|
|
327
|
+
let display = editable_value.display_value(name_attr)
|
|
328
|
+
|
|
329
|
+
// ActionValue 실행
|
|
330
|
+
let on_save: Option(ActionValue) = mendix.get_prop(props, "onSave")
|
|
331
|
+
action.execute_action(on_save)
|
|
332
|
+
// ...
|
|
333
|
+
}
|
|
334
|
+
\`\`\`
|
|
335
|
+
|
|
291
336
|
## 시작하기
|
|
292
337
|
|
|
293
338
|
### 사전 요구사항
|
|
@@ -338,10 +383,109 @@ src/
|
|
|
338
383
|
components/
|
|
339
384
|
hello_world.gleam # Hello World 공유 컴포넌트
|
|
340
385
|
${names.pascalCase}.xml # 위젯 속성 정의
|
|
386
|
+
widgets/ # .mpk 위젯 파일 (glendix/widget로 바인딩)
|
|
387
|
+
bindings.json # 외부 React 컴포넌트 바인딩 설정
|
|
388
|
+
package.json # npm 의존성 (React, 외부 라이브러리 등)
|
|
341
389
|
\`\`\`
|
|
342
390
|
|
|
343
391
|
React/Mendix FFI 바인딩은 [glendix](https://hexdocs.pm/glendix/) Hex 패키지로 제공됩니다.
|
|
344
392
|
|
|
393
|
+
## 외부 React 컴포넌트 사용
|
|
394
|
+
|
|
395
|
+
npm 패키지로 제공되는 React 컴포넌트 라이브러리를 \`.mjs\` FFI 파일 작성 없이 순수 Gleam에서 사용할 수 있다.
|
|
396
|
+
|
|
397
|
+
### 1단계: npm 패키지 설치
|
|
398
|
+
|
|
399
|
+
\`\`\`bash
|
|
400
|
+
${pm === "npm" ? "npm install" : pm === "yarn" ? "yarn add" : pm === "pnpm" ? "pnpm add" : "bun add"} recharts
|
|
401
|
+
\`\`\`
|
|
402
|
+
|
|
403
|
+
### 2단계: \`bindings.json\` 작성
|
|
404
|
+
|
|
405
|
+
프로젝트 루트에 \`bindings.json\`을 생성하고, 사용할 컴포넌트를 등록한다:
|
|
406
|
+
|
|
407
|
+
\`\`\`json
|
|
408
|
+
{
|
|
409
|
+
"recharts": {
|
|
410
|
+
"components": ["PieChart", "Pie", "Cell", "Tooltip", "ResponsiveContainer"]
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
\`\`\`
|
|
414
|
+
|
|
415
|
+
### 3단계: 바인딩 생성
|
|
416
|
+
|
|
417
|
+
\`\`\`bash
|
|
418
|
+
gleam run -m glendix/install
|
|
419
|
+
\`\`\`
|
|
420
|
+
|
|
421
|
+
\`binding_ffi.mjs\`가 자동 생성된다. 이후 \`gleam run -m glendix/build\` 등 빌드 시에도 자동 갱신된다.
|
|
422
|
+
|
|
423
|
+
### 4단계: Gleam에서 사용
|
|
424
|
+
|
|
425
|
+
\`\`\`gleam
|
|
426
|
+
import glendix/binding
|
|
427
|
+
import glendix/react.{type ReactElement}
|
|
428
|
+
import glendix/react/attribute.{type Attribute}
|
|
429
|
+
|
|
430
|
+
fn m() { binding.module("recharts") }
|
|
431
|
+
|
|
432
|
+
pub fn pie_chart(attrs: List(Attribute), children: List(ReactElement)) -> ReactElement {
|
|
433
|
+
react.component_el(binding.resolve(m(), "PieChart"), attrs, children)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
pub fn tooltip(attrs: List(Attribute)) -> ReactElement {
|
|
437
|
+
react.void_component_el(binding.resolve(m(), "Tooltip"), attrs)
|
|
438
|
+
}
|
|
439
|
+
\`\`\`
|
|
440
|
+
|
|
441
|
+
\`html.div\`와 동일한 호출 패턴으로 외부 React 컴포넌트를 사용할 수 있다.
|
|
442
|
+
|
|
443
|
+
## .mpk 위젯 컴포넌트 사용
|
|
444
|
+
|
|
445
|
+
\`widgets/\` 디렉토리에 \`.mpk\` 파일(Mendix 위젯 빌드 결과물)을 배치하면, 다른 위젯 안에서 기존 Mendix 위젯을 React 컴포넌트로 렌더링할 수 있다.
|
|
446
|
+
|
|
447
|
+
### 1단계: \`.mpk\` 파일 배치
|
|
448
|
+
|
|
449
|
+
\`\`\`
|
|
450
|
+
프로젝트 루트/
|
|
451
|
+
├── widgets/
|
|
452
|
+
│ ├── Switch.mpk
|
|
453
|
+
│ └── Badge.mpk
|
|
454
|
+
├── src/
|
|
455
|
+
└── gleam.toml
|
|
456
|
+
\`\`\`
|
|
457
|
+
|
|
458
|
+
### 2단계: 바인딩 생성
|
|
459
|
+
|
|
460
|
+
\`\`\`bash
|
|
461
|
+
gleam run -m glendix/install
|
|
462
|
+
\`\`\`
|
|
463
|
+
|
|
464
|
+
실행 시 다음이 자동 처리된다:
|
|
465
|
+
- \`.mpk\`에서 \`.mjs\`/\`.css\`를 추출하고 \`widget_ffi.mjs\`가 생성된다
|
|
466
|
+
- \`.mpk\` XML의 \`<property>\` 정의가 부모 위젯 XML에 자동 주입된다
|
|
467
|
+
|
|
468
|
+
### 3단계: Gleam에서 사용
|
|
469
|
+
|
|
470
|
+
\`\`\`gleam
|
|
471
|
+
import glendix/mendix
|
|
472
|
+
import glendix/widget
|
|
473
|
+
import glendix/react
|
|
474
|
+
import glendix/react/attribute
|
|
475
|
+
|
|
476
|
+
// props에서 자동 주입된 속성을 읽어 위젯에 전달
|
|
477
|
+
let boolean_attr = mendix.get_prop_required(props, "booleanAttribute")
|
|
478
|
+
let action = mendix.get_prop_required(props, "action")
|
|
479
|
+
|
|
480
|
+
let switch_comp = widget.component("Switch")
|
|
481
|
+
react.component_el(switch_comp, [
|
|
482
|
+
attribute.attribute("booleanAttribute", boolean_attr),
|
|
483
|
+
attribute.attribute("action", action),
|
|
484
|
+
], [])
|
|
485
|
+
\`\`\`
|
|
486
|
+
|
|
487
|
+
위젯 이름은 \`.mpk\` 내부 XML의 \`<name>\` 값(PascalCase)을, property key는 \`.mpk\` XML의 원본 key를 그대로 사용한다.
|
|
488
|
+
|
|
345
489
|
## 기술 스택
|
|
346
490
|
|
|
347
491
|
- **Gleam** → JavaScript 컴파일
|