create-mendix-widget-gleam 4.0.0 → 4.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 +2 -3
- package/package.json +1 -1
- package/src/index.mjs +0 -2
- package/src/templates/claude_md.mjs +1 -2
- package/src/templates/readme_md.mjs +0 -264
- package/template/docs/glendix_guide.md +3 -57
- package/template/docs/mendraw_guide.md +11 -354
- package/template/gleam.toml +2 -2
- package/src/templates/widgets_readme.mjs +0 -275
- package/template/widgets/README.md +0 -1
package/README.md
CHANGED
|
@@ -27,9 +27,8 @@ my-widget/
|
|
|
27
27
|
editor_preview.gleam # Studio Pro 디자인 뷰 미리보기
|
|
28
28
|
components/
|
|
29
29
|
hello_world.gleam # Hello World 공유 컴포넌트
|
|
30
|
-
widgets/ # .mpk 위젯 파일 (mendraw/widget로 바인딩)
|
|
31
30
|
package.json # npm 의존성 (React, 외부 라이브러리 등)
|
|
32
|
-
gleam.toml # Gleam 프로젝트 설정 (glendix >= 4.0.
|
|
31
|
+
gleam.toml # Gleam 프로젝트 설정 (glendix >= 4.0.3 + mendraw >= 1.1.11 의존성 포함)
|
|
33
32
|
CLAUDE.md # AI 어시스턴트용 프로젝트 컨텍스트
|
|
34
33
|
```
|
|
35
34
|
|
|
@@ -51,7 +50,7 @@ gleam run -m glendix/define # 위젯 프로퍼티 정의 TUI 에디터
|
|
|
51
50
|
생성된 프로젝트는 [glendix](https://hexdocs.pm/glendix/) Hex 패키지를 의존성으로 사용한다. glendix가 React 원시 함수와 Mendix Pluggable Widget API 전체에 대한 타입 안전한 Gleam 바인딩을 제공한다:
|
|
52
51
|
|
|
53
52
|
- **React** — `redraw`, `redraw/dom/attribute`, `redraw/hooks`, `redraw/dom/events`, `redraw/dom/html`, `redraw/dom/svg`; bindings via `glendix/binding`
|
|
54
|
-
- **Mendix** (mendraw) — `mendraw/mendix`, `mendraw/mendix/editable_value`, `mendraw/mendix/action`, `mendraw/mendix/list_value`, `mendraw/mendix/selection`, `mendraw/mendix/reference`, `mendraw/mendix/reference_set`, `mendraw/mendix/date`, `mendraw/mendix/decimal`, `mendraw/mendix/filter
|
|
53
|
+
- **Mendix** (mendraw) — `mendraw/mendix`, `mendraw/mendix/editable_value`, `mendraw/mendix/action`, `mendraw/mendix/list_value`, `mendraw/mendix/selection`, `mendraw/mendix/reference`, `mendraw/mendix/reference_set`, `mendraw/mendix/date`, `mendraw/mendix/decimal`, `mendraw/mendix/filter` 등
|
|
55
54
|
- **JS Interop** (glendix) — `glendix/js/array`, `glendix/js/object`, `glendix/js/json`, `glendix/js/promise`, `glendix/js/dom`, `glendix/js/timer`
|
|
56
55
|
|
|
57
56
|
## 라이선스
|
package/package.json
CHANGED
package/src/index.mjs
CHANGED
|
@@ -14,7 +14,6 @@ import { scaffold } from "./scaffold.mjs";
|
|
|
14
14
|
import { t, getTemplateComments, getLangLabel } from "./i18n.mjs";
|
|
15
15
|
import { generateClaudeMdContent } from "./templates/claude_md.mjs";
|
|
16
16
|
import { generateReadmeContent } from "./templates/readme_md.mjs";
|
|
17
|
-
import { generateWidgetsReadmeContent } from "./templates/widgets_readme.mjs";
|
|
18
17
|
import { generateLicenseContent } from "./licenses.mjs";
|
|
19
18
|
|
|
20
19
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -151,7 +150,6 @@ export async function main(args) {
|
|
|
151
150
|
// Build template comments (i18n for template placeholders)
|
|
152
151
|
const templateComments = {
|
|
153
152
|
...getTemplateComments(lang),
|
|
154
|
-
widgets_readme: generateWidgetsReadmeContent(lang),
|
|
155
153
|
};
|
|
156
154
|
|
|
157
155
|
// Scaffold options
|
|
@@ -63,7 +63,6 @@ Widget entry point signature: \`pub fn widget(props: JsProps) -> Element\` — i
|
|
|
63
63
|
- \`src/${names.pascalCase}.xml\` — Widget property definitions. Adding \`<property>\` triggers automatic type generation by the build tool
|
|
64
64
|
- \`src/package.xml\` — Mendix package manifest
|
|
65
65
|
- \`gleam.toml [tools.glendix.bindings]\` — External React component binding configuration
|
|
66
|
-
- \`widgets/\` — .mpk widget file bindings (used via \`mendraw/widget\`)
|
|
67
66
|
|
|
68
67
|
## Build Pipeline
|
|
69
68
|
|
|
@@ -94,7 +93,7 @@ src/*.gleam → gleam build → build/dev/javascript/**/*.mjs → Bridge JS (aut
|
|
|
94
93
|
For detailed glendix API and Gleam syntax, see:
|
|
95
94
|
|
|
96
95
|
- docs/glendix_guide.md — Complete React/Mendix bindings guide (elements, Hooks, events, Mendix types, practical patterns, troubleshooting)
|
|
97
|
-
- docs/mendraw_guide.md — mendraw usage guide (
|
|
96
|
+
- docs/mendraw_guide.md — mendraw usage guide (Marketplace download, classic widget support)
|
|
98
97
|
- docs/gleam_language_tour.md — Gleam syntax reference (types, pattern matching, FFI, use keyword, etc.)
|
|
99
98
|
|
|
100
99
|
## Mendix Documentation Sources
|
|
@@ -122,7 +122,6 @@ src/
|
|
|
122
122
|
components/
|
|
123
123
|
hello_world.gleam # Shared Hello World component
|
|
124
124
|
${names.pascalCase}.xml # Widget property definitions
|
|
125
|
-
widgets/ # .mpk widget files (bindings via mendraw/widget)
|
|
126
125
|
package.json # npm dependencies (React, external libraries, etc.)
|
|
127
126
|
\`\`\`
|
|
128
127
|
|
|
@@ -176,93 +175,6 @@ pub fn tooltip(attrs: List(Attribute)) -> Element {
|
|
|
176
175
|
|
|
177
176
|
External React components follow the same calling pattern as \`html.div\`.
|
|
178
177
|
|
|
179
|
-
## Mendix Marketplace Widget Download
|
|
180
|
-
|
|
181
|
-
Interactively search and download widgets (.mpk) from the Mendix Marketplace. After download, binding \`.gleam\` files are generated automatically and ready to use.
|
|
182
|
-
|
|
183
|
-
### Preparation
|
|
184
|
-
|
|
185
|
-
Set your Mendix Personal Access Token in a \`.env\` file:
|
|
186
|
-
|
|
187
|
-
\`\`\`
|
|
188
|
-
MENDIX_PAT=your_personal_access_token
|
|
189
|
-
\`\`\`
|
|
190
|
-
|
|
191
|
-
> Generate a PAT from [Mendix Developer Settings](https://user-settings.mendix.com/link/developersettings) — click **New Token** under **Personal Access Tokens**. Required scope: \`mx:marketplace-content:read\`
|
|
192
|
-
|
|
193
|
-
### Run
|
|
194
|
-
|
|
195
|
-
\`\`\`bash
|
|
196
|
-
gleam run -m mendraw/marketplace
|
|
197
|
-
\`\`\`
|
|
198
|
-
|
|
199
|
-
Search and select widgets in the interactive TUI. The \`.mpk\` is downloaded to the \`widgets/\` directory, and binding \`.gleam\` files are auto-generated in \`src/widgets/\`.
|
|
200
|
-
|
|
201
|
-
## Using .mpk Widget Components
|
|
202
|
-
|
|
203
|
-
Place \`.mpk\` files (Mendix widget build artifacts) in the \`widgets/\` directory to render existing Mendix widgets as React components within your own widget.
|
|
204
|
-
|
|
205
|
-
### Step 1: Place the \`.mpk\` files
|
|
206
|
-
|
|
207
|
-
\`\`\`
|
|
208
|
-
project root/
|
|
209
|
-
├── widgets/
|
|
210
|
-
│ ├── Switch.mpk
|
|
211
|
-
│ └── Badge.mpk
|
|
212
|
-
├── src/
|
|
213
|
-
└── gleam.toml
|
|
214
|
-
\`\`\`
|
|
215
|
-
|
|
216
|
-
### Step 2: Generate bindings
|
|
217
|
-
|
|
218
|
-
\`\`\`bash
|
|
219
|
-
gleam run -m glendix/install
|
|
220
|
-
\`\`\`
|
|
221
|
-
|
|
222
|
-
This automatically:
|
|
223
|
-
- Extracts \`.mjs\`/\`.css\` from \`.mpk\` and generates \`widget_ffi.mjs\`
|
|
224
|
-
- Parses \`<property>\` definitions from \`.mpk\` XML and generates binding \`.gleam\` files in \`src/widgets/\` (existing files are skipped)
|
|
225
|
-
|
|
226
|
-
### Step 3: Review auto-generated \`src/widgets/*.gleam\` files
|
|
227
|
-
|
|
228
|
-
\`\`\`gleam
|
|
229
|
-
// src/widgets/switch.gleam (auto-generated)
|
|
230
|
-
import mendraw/mendix.{type JsProps}
|
|
231
|
-
import mendraw/interop
|
|
232
|
-
import redraw.{type Element}
|
|
233
|
-
import redraw/dom/attribute
|
|
234
|
-
import mendraw/widget
|
|
235
|
-
|
|
236
|
-
/// Render Switch widget - reads properties from props and passes them to the widget
|
|
237
|
-
pub fn render(props: JsProps) -> Element {
|
|
238
|
-
let boolean_attribute = mendix.get_prop_required(props, "booleanAttribute")
|
|
239
|
-
let action = mendix.get_prop_required(props, "action")
|
|
240
|
-
|
|
241
|
-
let comp = widget.component("Switch")
|
|
242
|
-
interop.component_el(
|
|
243
|
-
comp,
|
|
244
|
-
[
|
|
245
|
-
attribute.attribute("booleanAttribute", boolean_attribute),
|
|
246
|
-
attribute.attribute("action", action),
|
|
247
|
-
],
|
|
248
|
-
[],
|
|
249
|
-
)
|
|
250
|
-
}
|
|
251
|
-
\`\`\`
|
|
252
|
-
|
|
253
|
-
Required/optional properties are distinguished automatically. You can freely modify the generated files as needed.
|
|
254
|
-
|
|
255
|
-
### Step 4: Use in your widget
|
|
256
|
-
|
|
257
|
-
\`\`\`gleam
|
|
258
|
-
import widgets/switch
|
|
259
|
-
|
|
260
|
-
// Inside a component
|
|
261
|
-
switch.render(props)
|
|
262
|
-
\`\`\`
|
|
263
|
-
|
|
264
|
-
Widget names use the \`<name>\` value from the \`.mpk\`'s internal XML, and property keys use the original keys from the \`.mpk\` XML.
|
|
265
|
-
|
|
266
178
|
## Tech Stack
|
|
267
179
|
|
|
268
180
|
- **Gleam** → JavaScript compilation
|
|
@@ -378,7 +290,6 @@ src/
|
|
|
378
290
|
components/
|
|
379
291
|
hello_world.gleam # Hello World 공유 컴포넌트
|
|
380
292
|
${names.pascalCase}.xml # 위젯 속성 정의
|
|
381
|
-
widgets/ # .mpk 위젯 파일 (mendraw/widget로 바인딩)
|
|
382
293
|
package.json # npm 의존성 (React, 외부 라이브러리 등)
|
|
383
294
|
\`\`\`
|
|
384
295
|
|
|
@@ -432,93 +343,6 @@ pub fn tooltip(attrs: List(Attribute)) -> Element {
|
|
|
432
343
|
|
|
433
344
|
\`html.div\`와 동일한 호출 패턴으로 외부 React 컴포넌트를 사용할 수 있다.
|
|
434
345
|
|
|
435
|
-
## Mendix Marketplace 위젯 다운로드
|
|
436
|
-
|
|
437
|
-
Mendix Marketplace에서 위젯(.mpk)을 인터랙티브하게 검색하고 다운로드할 수 있다. 다운로드 완료 후 바인딩 \`.gleam\` 파일이 자동 생성되어 바로 사용 가능하다.
|
|
438
|
-
|
|
439
|
-
### 사전 준비
|
|
440
|
-
|
|
441
|
-
\`.env\` 파일에 Mendix Personal Access Token을 설정한다:
|
|
442
|
-
|
|
443
|
-
\`\`\`
|
|
444
|
-
MENDIX_PAT=your_personal_access_token
|
|
445
|
-
\`\`\`
|
|
446
|
-
|
|
447
|
-
> PAT는 [Mendix Developer Settings](https://user-settings.mendix.com/link/developersettings)에서 **Personal Access Tokens** 섹션의 **New Token**을 클릭하여 발급. 필요한 scope: \`mx:marketplace-content:read\`
|
|
448
|
-
|
|
449
|
-
### 실행
|
|
450
|
-
|
|
451
|
-
\`\`\`bash
|
|
452
|
-
gleam run -m mendraw/marketplace
|
|
453
|
-
\`\`\`
|
|
454
|
-
|
|
455
|
-
인터랙티브 TUI에서 위젯을 검색/선택하면 \`widgets/\` 디렉토리에 \`.mpk\`가 다운로드되고, \`src/widgets/\`에 바인딩 \`.gleam\` 파일이 자동 생성된다.
|
|
456
|
-
|
|
457
|
-
## .mpk 위젯 컴포넌트 사용
|
|
458
|
-
|
|
459
|
-
\`widgets/\` 디렉토리에 \`.mpk\` 파일(Mendix 위젯 빌드 결과물)을 배치하면, 다른 위젯 안에서 기존 Mendix 위젯을 React 컴포넌트로 렌더링할 수 있다.
|
|
460
|
-
|
|
461
|
-
### 1단계: \`.mpk\` 파일 배치
|
|
462
|
-
|
|
463
|
-
\`\`\`
|
|
464
|
-
프로젝트 루트/
|
|
465
|
-
├── widgets/
|
|
466
|
-
│ ├── Switch.mpk
|
|
467
|
-
│ └── Badge.mpk
|
|
468
|
-
├── src/
|
|
469
|
-
└── gleam.toml
|
|
470
|
-
\`\`\`
|
|
471
|
-
|
|
472
|
-
### 2단계: 바인딩 생성
|
|
473
|
-
|
|
474
|
-
\`\`\`bash
|
|
475
|
-
gleam run -m glendix/install
|
|
476
|
-
\`\`\`
|
|
477
|
-
|
|
478
|
-
실행 시 다음이 자동 처리된다:
|
|
479
|
-
- \`.mpk\`에서 \`.mjs\`/\`.css\`를 추출하고 \`widget_ffi.mjs\`가 생성된다
|
|
480
|
-
- \`.mpk\` XML의 \`<property>\` 정의를 파싱하여 \`src/widgets/\`에 바인딩 \`.gleam\` 파일이 자동 생성된다 (이미 존재하면 건너뜀)
|
|
481
|
-
|
|
482
|
-
### 3단계: 자동 생성된 \`src/widgets/*.gleam\` 파일 확인
|
|
483
|
-
|
|
484
|
-
\`\`\`gleam
|
|
485
|
-
// src/widgets/switch.gleam (자동 생성)
|
|
486
|
-
import mendraw/mendix.{type JsProps}
|
|
487
|
-
import mendraw/interop
|
|
488
|
-
import redraw.{type Element}
|
|
489
|
-
import redraw/dom/attribute
|
|
490
|
-
import mendraw/widget
|
|
491
|
-
|
|
492
|
-
/// Switch 위젯 렌더링 - props에서 속성을 읽어 위젯에 전달
|
|
493
|
-
pub fn render(props: JsProps) -> Element {
|
|
494
|
-
let boolean_attribute = mendix.get_prop_required(props, "booleanAttribute")
|
|
495
|
-
let action = mendix.get_prop_required(props, "action")
|
|
496
|
-
|
|
497
|
-
let comp = widget.component("Switch")
|
|
498
|
-
interop.component_el(
|
|
499
|
-
comp,
|
|
500
|
-
[
|
|
501
|
-
attribute.attribute("booleanAttribute", boolean_attribute),
|
|
502
|
-
attribute.attribute("action", action),
|
|
503
|
-
],
|
|
504
|
-
[],
|
|
505
|
-
)
|
|
506
|
-
}
|
|
507
|
-
\`\`\`
|
|
508
|
-
|
|
509
|
-
required/optional 속성이 자동 구분되며, 필요에 따라 생성된 파일을 자유롭게 수정할 수 있다.
|
|
510
|
-
|
|
511
|
-
### 4단계: 위젯에서 사용
|
|
512
|
-
|
|
513
|
-
\`\`\`gleam
|
|
514
|
-
import widgets/switch
|
|
515
|
-
|
|
516
|
-
// 컴포넌트 내부에서
|
|
517
|
-
switch.render(props)
|
|
518
|
-
\`\`\`
|
|
519
|
-
|
|
520
|
-
위젯 이름은 \`.mpk\` 내부 XML의 \`<name>\` 값을, property key는 \`.mpk\` XML의 원본 key를 그대로 사용한다.
|
|
521
|
-
|
|
522
346
|
## 기술 스택
|
|
523
347
|
|
|
524
348
|
- **Gleam** → JavaScript 컴파일
|
|
@@ -634,7 +458,6 @@ src/
|
|
|
634
458
|
components/
|
|
635
459
|
hello_world.gleam # Hello World共有コンポーネント
|
|
636
460
|
${names.pascalCase}.xml # ウィジェットプロパティ定義
|
|
637
|
-
widgets/ # .mpkウィジェットファイル(mendraw/widgetでバインディング)
|
|
638
461
|
package.json # npm依存関係(React、外部ライブラリなど)
|
|
639
462
|
\`\`\`
|
|
640
463
|
|
|
@@ -688,93 +511,6 @@ pub fn tooltip(attrs: List(Attribute)) -> Element {
|
|
|
688
511
|
|
|
689
512
|
\`html.div\`と同じ呼び出しパターンで外部Reactコンポーネントを使用できる。
|
|
690
513
|
|
|
691
|
-
## Mendix Marketplaceウィジェットのダウンロード
|
|
692
|
-
|
|
693
|
-
Mendix Marketplaceからウィジェット(.mpk)をインタラクティブに検索・ダウンロードできる。ダウンロード完了後、バインディング\`.gleam\`ファイルが自動生成され、すぐに使用可能になる。
|
|
694
|
-
|
|
695
|
-
### 事前準備
|
|
696
|
-
|
|
697
|
-
\`.env\`ファイルにMendix Personal Access Tokenを設定する:
|
|
698
|
-
|
|
699
|
-
\`\`\`
|
|
700
|
-
MENDIX_PAT=your_personal_access_token
|
|
701
|
-
\`\`\`
|
|
702
|
-
|
|
703
|
-
> PATは[Mendix Developer Settings](https://user-settings.mendix.com/link/developersettings)の**Personal Access Tokens**セクションで**New Token**をクリックして発行。必要なscope:\`mx:marketplace-content:read\`
|
|
704
|
-
|
|
705
|
-
### 実行
|
|
706
|
-
|
|
707
|
-
\`\`\`bash
|
|
708
|
-
gleam run -m mendraw/marketplace
|
|
709
|
-
\`\`\`
|
|
710
|
-
|
|
711
|
-
インタラクティブTUIでウィジェットを検索・選択すると、\`widgets/\`ディレクトリに\`.mpk\`がダウンロードされ、\`src/widgets/\`にバインディング\`.gleam\`ファイルが自動生成される。
|
|
712
|
-
|
|
713
|
-
## .mpkウィジェットコンポーネントの使用
|
|
714
|
-
|
|
715
|
-
\`widgets/\`ディレクトリに\`.mpk\`ファイル(Mendixウィジェットビルド成果物)を配置すると、別のウィジェット内から既存のMendixウィジェットをReactコンポーネントとしてレンダリングできる。
|
|
716
|
-
|
|
717
|
-
### ステップ1:\`.mpk\`ファイルの配置
|
|
718
|
-
|
|
719
|
-
\`\`\`
|
|
720
|
-
プロジェクトルート/
|
|
721
|
-
├── widgets/
|
|
722
|
-
│ ├── Switch.mpk
|
|
723
|
-
│ └── Badge.mpk
|
|
724
|
-
├── src/
|
|
725
|
-
└── gleam.toml
|
|
726
|
-
\`\`\`
|
|
727
|
-
|
|
728
|
-
### ステップ2:バインディングの生成
|
|
729
|
-
|
|
730
|
-
\`\`\`bash
|
|
731
|
-
gleam run -m glendix/install
|
|
732
|
-
\`\`\`
|
|
733
|
-
|
|
734
|
-
実行時に以下が自動処理される:
|
|
735
|
-
- \`.mpk\`から\`.mjs\`/\`.css\`を抽出し、\`widget_ffi.mjs\`が生成される
|
|
736
|
-
- \`.mpk\` XMLの\`<property>\`定義をパースし、\`src/widgets/\`にバインディング\`.gleam\`ファイルが自動生成される(既存ファイルはスキップ)
|
|
737
|
-
|
|
738
|
-
### ステップ3:自動生成された\`src/widgets/*.gleam\`ファイルの確認
|
|
739
|
-
|
|
740
|
-
\`\`\`gleam
|
|
741
|
-
// src/widgets/switch.gleam(自動生成)
|
|
742
|
-
import mendraw/mendix.{type JsProps}
|
|
743
|
-
import mendraw/interop
|
|
744
|
-
import redraw.{type Element}
|
|
745
|
-
import redraw/dom/attribute
|
|
746
|
-
import mendraw/widget
|
|
747
|
-
|
|
748
|
-
/// Switchウィジェットのレンダリング - propsからプロパティを読み取りウィジェットに渡す
|
|
749
|
-
pub fn render(props: JsProps) -> Element {
|
|
750
|
-
let boolean_attribute = mendix.get_prop_required(props, "booleanAttribute")
|
|
751
|
-
let action = mendix.get_prop_required(props, "action")
|
|
752
|
-
|
|
753
|
-
let comp = widget.component("Switch")
|
|
754
|
-
interop.component_el(
|
|
755
|
-
comp,
|
|
756
|
-
[
|
|
757
|
-
attribute.attribute("booleanAttribute", boolean_attribute),
|
|
758
|
-
attribute.attribute("action", action),
|
|
759
|
-
],
|
|
760
|
-
[],
|
|
761
|
-
)
|
|
762
|
-
}
|
|
763
|
-
\`\`\`
|
|
764
|
-
|
|
765
|
-
required/optionalプロパティは自動的に区別され、生成されたファイルは自由に編集できる。
|
|
766
|
-
|
|
767
|
-
### ステップ4:ウィジェットで使用
|
|
768
|
-
|
|
769
|
-
\`\`\`gleam
|
|
770
|
-
import widgets/switch
|
|
771
|
-
|
|
772
|
-
// コンポーネント内で
|
|
773
|
-
switch.render(props)
|
|
774
|
-
\`\`\`
|
|
775
|
-
|
|
776
|
-
ウィジェット名は\`.mpk\`内部XMLの\`<name>\`値を、プロパティキーは\`.mpk\` XMLの元のキーをそのまま使用する。
|
|
777
|
-
|
|
778
514
|
## 技術スタック
|
|
779
515
|
|
|
780
516
|
- **Gleam** → JavaScriptコンパイル
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# glendix v4.0.
|
|
1
|
+
# glendix v4.0.3 — Agent Reference Guide
|
|
2
2
|
|
|
3
3
|
> 이 문서는 AI 에이전트(LLM)가 glendix 코드를 작성할 때 참조하는 가이드입니다. 각 섹션은 독립적으로 읽을 수 있습니다.
|
|
4
4
|
|
|
@@ -46,8 +46,8 @@ glendix는 Gleam으로 Mendix Pluggable Widget을 작성하는 FFI 라이브러
|
|
|
46
46
|
|
|
47
47
|
```toml
|
|
48
48
|
[dependencies]
|
|
49
|
-
glendix = ">= 4.0.
|
|
50
|
-
mendraw = ">= 1.1.
|
|
49
|
+
glendix = ">= 4.0.3 and < 5.0.0"
|
|
50
|
+
mendraw = ">= 1.1.11 and < 2.0.0"
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Peer dependency (위젯 프로젝트 `package.json`):
|
|
@@ -416,7 +416,6 @@ fn view(model: Model) {
|
|
|
416
416
|
| 컴포넌트 출처 | 사용 모듈 | 예시 |
|
|
417
417
|
|--------------|----------|------|
|
|
418
418
|
| npm 패키지 (React 컴포넌트) | `glendix/binding` + `mendraw/interop` | recharts, @mui |
|
|
419
|
-
| `.mpk` Pluggable 위젯 (gleam.toml) | `mendraw/widget` + `mendraw/interop` | Switch, Badge |
|
|
420
419
|
| `.mpk` Classic (Dojo) 위젯 (gleam.toml) | `mendraw/classic` | CameraWidget |
|
|
421
420
|
|
|
422
421
|
### 7.2 외부 React 컴포넌트 (binding + interop)
|
|
@@ -455,57 +454,6 @@ pub fn tooltip(attrs: List(Attribute)) -> Element {
|
|
|
455
454
|
| `interop.component_el_(comp, children)` | 자식만 |
|
|
456
455
|
| `interop.void_component_el(comp, attrs)` | self-closing (자식 없음) |
|
|
457
456
|
|
|
458
|
-
### 7.3 .mpk Pluggable 위젯 (widget + interop)
|
|
459
|
-
|
|
460
|
-
`gleam.toml`에 위젯을 등록하고 `gleam run -m glendix/install`로 자동 다운로드합니다:
|
|
461
|
-
|
|
462
|
-
```toml
|
|
463
|
-
[tools.mendraw.widgets.Charts]
|
|
464
|
-
version = "3.0.0"
|
|
465
|
-
# s3_id = "com/..." ← 있으면 인증 없이 직접 다운로드
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
`build/widgets/`에 캐시하고 바인딩을 자동 생성합니다.
|
|
469
|
-
Marketplace TUI(`gleam run -m mendraw/marketplace`)에서 다운로드하면 gleam.toml에 자동 추가됩니다.
|
|
470
|
-
|
|
471
|
-
자동 생성되는 `src/widgets/*.gleam`:
|
|
472
|
-
|
|
473
|
-
```gleam
|
|
474
|
-
import mendraw/interop
|
|
475
|
-
import mendraw/mendix
|
|
476
|
-
import mendraw/mendix.{type JsProps}
|
|
477
|
-
import mendraw/widget
|
|
478
|
-
import redraw.{type Element}
|
|
479
|
-
import redraw/dom/attribute
|
|
480
|
-
|
|
481
|
-
pub fn render(props: JsProps) -> Element {
|
|
482
|
-
let boolean_attribute = mendix.get_prop_required(props, "booleanAttribute")
|
|
483
|
-
let comp = widget.component("Switch")
|
|
484
|
-
interop.component_el(comp, [
|
|
485
|
-
attribute.attribute("booleanAttribute", boolean_attribute),
|
|
486
|
-
], [])
|
|
487
|
-
}
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
**위젯 prop 헬퍼:** 코드에서 직접 값을 생성하여 .mpk 위젯에 전달할 때 사용합니다.
|
|
491
|
-
|
|
492
|
-
| 함수 | Mendix 타입 | 용도 |
|
|
493
|
-
|------|------------|------|
|
|
494
|
-
| `widget.prop(key, value)` | DynamicValue | 읽기 전용 (expression, textTemplate) |
|
|
495
|
-
| `widget.editable_prop(key, value, display, set_value)` | EditableValue | 편집 가능한 속성 |
|
|
496
|
-
| `widget.action_prop(key, handler)` | ActionValue | 액션 콜백 (onClick 등) |
|
|
497
|
-
|
|
498
|
-
```gleam
|
|
499
|
-
import mendraw/widget
|
|
500
|
-
import mendraw/interop
|
|
501
|
-
|
|
502
|
-
let comp = widget.component("Badge button")
|
|
503
|
-
interop.component_el(comp, [
|
|
504
|
-
widget.prop("caption", "제목"),
|
|
505
|
-
widget.editable_prop("textAttr", model.text, model.text, set_text),
|
|
506
|
-
widget.action_prop("onClick", fn() { handle_click() }),
|
|
507
|
-
], [])
|
|
508
|
-
```
|
|
509
457
|
|
|
510
458
|
> Mendix에서 받은 prop (JsProps에서 꺼낸 값)은 이미 올바른 형식이므로 `attribute.attribute(key, value)`로 그대로 전달합니다.
|
|
511
459
|
|
|
@@ -1140,7 +1088,6 @@ pub fn searchable_list(props: JsProps) -> Element {
|
|
|
1140
1088
|
| `html.text("")`로 빈 렌더링 | `html.none()` 사용 |
|
|
1141
1089
|
| `binding.resolve(m(), "pie_chart")` | JS 원본 이름 유지: `"PieChart"` |
|
|
1142
1090
|
| 외부 React 컴포넌트용 `.mjs` 직접 작성 | `gleam.toml [tools.glendix.bindings]` + `glendix/binding` 사용 |
|
|
1143
|
-
| `.mpk` 위젯용 `.mjs` 직접 작성 | `gleam.toml [tools.mendraw.widgets.*]` + `mendraw/widget` 사용 |
|
|
1144
1091
|
| `date.month()`에 0-based 값 전달 | glendix가 1↔0 자동 변환 |
|
|
1145
1092
|
| Editor config에서 Gleam List 사용 | 콤마 구분 String 사용 (Jint 호환) |
|
|
1146
1093
|
| FFI `.mjs`에 비즈니스 로직 | `.gleam`에 작성. `.mjs`는 JS 런타임 접근만 |
|
|
@@ -1155,7 +1102,6 @@ pub fn searchable_list(props: JsProps) -> Element {
|
|
|
1155
1102
|
| `Cannot read property of undefined` | 없는 prop 접근 | `get_prop` (Option) 사용, prop 이름 확인 |
|
|
1156
1103
|
| Hook 순서 에러 | 조건부 Hook 호출 | 항상 동일 순서로 호출 (React Rules) |
|
|
1157
1104
|
| 바인딩 미생성 | `binding_ffi.mjs` 스텁 상태 | `gleam run -m glendix/install` |
|
|
1158
|
-
| 위젯 바인딩 미생성 | `widget_ffi.mjs` 스텁 상태 | `gleam.toml [tools.mendraw.widgets.*]` 설정 후 install |
|
|
1159
1105
|
| `could not be resolved` | npm 패키지 미설치 | `npm install <패키지명>` |
|
|
1160
1106
|
| `.env` PAT 오류 | marketplace 인증 실패 | [Developer Settings](https://user-settings.mendix.com/link/developersettings)에서 PAT 재발급 |
|
|
1161
1107
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# mendraw 사용 가이드
|
|
2
2
|
|
|
3
|
-
Mendix 위젯
|
|
4
|
-
|
|
3
|
+
Mendix 위젯 Gleam/[redraw](https://hexdocs.pm/redraw/) 바인딩 라이브러리.
|
|
4
|
+
Classic(Dojo) 위젯 지원과 Marketplace 검색/다운로드 기능을 제공한다.
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -9,27 +9,15 @@ Pluggable(React) 위젯과 Classic(Dojo) 위젯을 모두 지원한다.
|
|
|
9
9
|
|
|
10
10
|
- [사전 준비](#사전-준비)
|
|
11
11
|
- [설치](#설치)
|
|
12
|
-
- [빠른 시작](#빠른-시작)
|
|
13
12
|
- [Marketplace에서 위젯 다운로드](#marketplace에서-위젯-다운로드)
|
|
14
|
-
- [
|
|
15
|
-
- [
|
|
16
|
-
- [Classic (Dojo) 위젯](#classic-dojo-위젯)
|
|
17
|
-
- [저수준 API로 직접 조립하기](#저수준-api로-직접-조립하기)
|
|
18
|
-
- [위젯 컴포넌트 조회](#위젯-컴포넌트-조회)
|
|
19
|
-
- [Prop 래핑](#prop-래핑)
|
|
20
|
-
- [컴포넌트 렌더링](#컴포넌트-렌더링)
|
|
13
|
+
- [Classic (Dojo) 위젯](#classic-dojo-위젯)
|
|
14
|
+
- [Classic 위젯 직접 렌더링](#classic-위젯-직접-렌더링)
|
|
21
15
|
- [JsProps 다루기](#jsprops-다루기)
|
|
22
16
|
- [Prop 접근자](#prop-접근자)
|
|
23
17
|
- [ValueStatus](#valuestatus)
|
|
24
18
|
- [Option 변환](#option-변환)
|
|
25
|
-
- [생성된 코드 구조](#생성된-코드-구조)
|
|
26
|
-
- [Pluggable 위젯 바인딩 예시](#pluggable-위젯-바인딩-예시)
|
|
27
|
-
- [Classic 위젯 바인딩 예시](#classic-위젯-바인딩-예시)
|
|
28
|
-
- [파일명 변환 규칙](#파일명-변환-규칙)
|
|
29
|
-
- [생성된 바인딩 커스터마이징](#생성된-바인딩-커스터마이징)
|
|
30
19
|
- [API 레퍼런스](#api-레퍼런스)
|
|
31
20
|
- [mendraw/mendix](#mendrawmendix)
|
|
32
|
-
- [mendraw/widget](#mendrawwidget)
|
|
33
21
|
- [mendraw/interop](#mendrawinterop)
|
|
34
22
|
- [mendraw/classic](#mendrawclassic)
|
|
35
23
|
- [mendraw/marketplace](#mendrawmarketplace)
|
|
@@ -57,7 +45,7 @@ gleam add mendraw@1
|
|
|
57
45
|
|
|
58
46
|
```toml
|
|
59
47
|
[dependencies]
|
|
60
|
-
mendraw = ">= 1.1.
|
|
48
|
+
mendraw = ">= 1.1.11 and < 2.0.0"
|
|
61
49
|
```
|
|
62
50
|
|
|
63
51
|
mendraw는 `gleam_stdlib`, `gleam_javascript`, `redraw`, `redraw_dom`을 함께 가져온다.
|
|
@@ -65,61 +53,9 @@ mendraw는 `gleam_stdlib`, `gleam_javascript`, `redraw`, `redraw_dom`을 함께
|
|
|
65
53
|
|
|
66
54
|
---
|
|
67
55
|
|
|
68
|
-
## 빠른 시작
|
|
69
|
-
|
|
70
|
-
### 1단계: 위젯 등록
|
|
71
|
-
|
|
72
|
-
**`gleam.toml`로 자동 다운로드**
|
|
73
|
-
|
|
74
|
-
```toml
|
|
75
|
-
[tools.mendraw.widgets.Charts]
|
|
76
|
-
version = "3.0.0"
|
|
77
|
-
# s3_id = "com/..." ← 있으면 인증 없이 직접 다운로드
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
`gleam run -m mendraw/install` 실행 시 `build/widgets/`에 캐시하고 바인딩을 자동 생성한다.
|
|
81
|
-
Marketplace TUI(`gleam run -m mendraw/marketplace`)에서 다운로드하면 gleam.toml에 자동 추가된다.
|
|
82
|
-
|
|
83
|
-
### 2단계: 바인딩 생성
|
|
84
|
-
|
|
85
|
-
```sh
|
|
86
|
-
gleam run -m mendraw/install
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
실행 결과:
|
|
90
|
-
|
|
91
|
-
- TOML에 등록된 위젯을 `build/widgets/`에 다운로드/캐시
|
|
92
|
-
- `src/widgets/`에 위젯별 `.gleam` 바인딩 파일이 생성된다
|
|
93
|
-
- 빌드 경로에 `widget_ffi.mjs`(컴포넌트 레지스트리)가 생성된다
|
|
94
|
-
- Classic 위젯이 있으면 `classic_ffi.mjs`(런타임)도 생성된다
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
src/widgets/
|
|
98
|
-
├── switch.gleam ← Pluggable 위젯
|
|
99
|
-
├── area_chart.gleam ← Charts.mpk에서 추출
|
|
100
|
-
├── bar_chart.gleam
|
|
101
|
-
└── camera_widget.gleam ← Classic 위젯
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### 3단계: 바인딩 사용
|
|
105
|
-
|
|
106
|
-
```gleam
|
|
107
|
-
import widgets/switch
|
|
108
|
-
import mendraw/mendix.{type JsProps}
|
|
109
|
-
import redraw.{type Element}
|
|
110
|
-
|
|
111
|
-
pub fn my_view(props: JsProps) -> Element {
|
|
112
|
-
switch.render(props)
|
|
113
|
-
}
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
이것으로 끝이다. 아래에서 각 단계를 자세히 설명한다.
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
56
|
## Marketplace에서 위젯 다운로드
|
|
121
57
|
|
|
122
|
-
|
|
58
|
+
Mendix Marketplace에서 위젯을 검색하고 다운로드할 수 있는 TUI를 제공한다.
|
|
123
59
|
|
|
124
60
|
### 사전 설정
|
|
125
61
|
|
|
@@ -176,8 +112,7 @@ gleam run -m mendraw/marketplace
|
|
|
176
112
|
|
|
177
113
|
### 다운로드 후
|
|
178
114
|
|
|
179
|
-
다운로드한 위젯은 `
|
|
180
|
-
다운로드가 1개 이상 완료되면 자동으로 `cmd.generate_widget_bindings()`가 실행되어 바인딩이 생성된다.
|
|
115
|
+
다운로드한 위젯은 `gleam.toml`의 `[tools.mendraw.widgets.*]`에 자동 추가된다.
|
|
181
116
|
|
|
182
117
|
> **참고**: 첫 다운로드 시 chrobot_extra 사이드카를 통한 Mendix 로그인이 필요할 수 있다.
|
|
183
118
|
> 로그인 세션은 `.marketplace-cache/session.json`에 캐시된다.
|
|
@@ -185,124 +120,7 @@ gleam run -m mendraw/marketplace
|
|
|
185
120
|
|
|
186
121
|
---
|
|
187
122
|
|
|
188
|
-
##
|
|
189
|
-
|
|
190
|
-
`gleam run -m mendraw/install`이 생성하는 `.gleam` 파일에는 `render` 함수가 포함된다.
|
|
191
|
-
이 함수는 Mendix가 전달하는 `JsProps`를 받아 `redraw` `Element`를 반환한다.
|
|
192
|
-
|
|
193
|
-
### Pluggable 위젯
|
|
194
|
-
|
|
195
|
-
Pluggable 위젯(React 기반)의 생성된 바인딩:
|
|
196
|
-
|
|
197
|
-
```gleam
|
|
198
|
-
import widgets/switch
|
|
199
|
-
import mendraw/mendix.{type JsProps}
|
|
200
|
-
import redraw.{type Element}
|
|
201
|
-
|
|
202
|
-
/// Mendix가 위젯에 전달하는 props를 그대로 넘긴다
|
|
203
|
-
pub fn view(props: JsProps) -> Element {
|
|
204
|
-
switch.render(props)
|
|
205
|
-
}
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
생성된 `render` 함수는 내부적으로:
|
|
209
|
-
1. `mendix.get_prop_required`/`mendix.get_prop`으로 props에서 속성을 추출
|
|
210
|
-
2. `widget.component`로 원본 React 컴포넌트를 가져옴
|
|
211
|
-
3. `interop.component_el`로 redraw Element를 생성
|
|
212
|
-
|
|
213
|
-
### Classic (Dojo) 위젯
|
|
214
|
-
|
|
215
|
-
Classic 위젯(Dojo 기반)의 생성된 바인딩:
|
|
216
|
-
|
|
217
|
-
```gleam
|
|
218
|
-
import widgets/camera_widget
|
|
219
|
-
import mendraw/mendix.{type JsProps}
|
|
220
|
-
import redraw.{type Element}
|
|
221
|
-
|
|
222
|
-
pub fn view(props: JsProps) -> Element {
|
|
223
|
-
camera_widget.render(props)
|
|
224
|
-
}
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
Classic 위젯은 내부적으로 DOM 컨테이너를 생성하고, `useEffect`로 위젯의 마운트/언마운트를 관리한다.
|
|
228
|
-
|
|
229
|
-
---
|
|
230
|
-
|
|
231
|
-
## 저수준 API로 직접 조립하기
|
|
232
|
-
|
|
233
|
-
생성된 바인딩 대신, `mendraw/widget`과 `mendraw/interop` 모듈을 직접 사용하여
|
|
234
|
-
위젯 렌더링을 세밀하게 제어할 수 있다.
|
|
235
|
-
|
|
236
|
-
### 위젯 컴포넌트 조회
|
|
237
|
-
|
|
238
|
-
```gleam
|
|
239
|
-
import mendraw/widget
|
|
240
|
-
|
|
241
|
-
// 위젯 이름으로 React 컴포넌트를 가져온다
|
|
242
|
-
let comp = widget.component("Switch")
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
위젯 이름은 `.mpk` 파일의 `widget.xml`에 정의된 `<name>` 값이다.
|
|
246
|
-
|
|
247
|
-
### Prop 래핑
|
|
248
|
-
|
|
249
|
-
Mendix 위젯은 일반 값이 아닌 래핑된 값 객체를 기대한다.
|
|
250
|
-
mendraw는 세 가지 prop 래퍼를 제공한다:
|
|
251
|
-
|
|
252
|
-
```gleam
|
|
253
|
-
import mendraw/widget
|
|
254
|
-
|
|
255
|
-
// 1. 읽기 전용 prop (DynamicValue)
|
|
256
|
-
// expression, textTemplate 등 읽기 전용 속성에 사용
|
|
257
|
-
widget.prop("caption", "제목 텍스트")
|
|
258
|
-
|
|
259
|
-
// 2. 편집 가능한 prop (EditableValue)
|
|
260
|
-
// 사용자 입력이 필요한 속성에 사용
|
|
261
|
-
widget.editable_prop("textAttr", current_value, "표시값", fn(new_val) {
|
|
262
|
-
// 값이 변경되었을 때의 처리
|
|
263
|
-
Nil
|
|
264
|
-
})
|
|
265
|
-
|
|
266
|
-
// 3. 액션 prop (ActionValue)
|
|
267
|
-
// onClick, onLeave 등 이벤트 핸들러에 사용
|
|
268
|
-
widget.action_prop("onClick", fn() {
|
|
269
|
-
// 클릭 시 처리
|
|
270
|
-
Nil
|
|
271
|
-
})
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
각 래퍼가 생성하는 Mendix 값 객체:
|
|
275
|
-
|
|
276
|
-
| 래퍼 | Mendix 타입 | 구조 |
|
|
277
|
-
|------|------------|------|
|
|
278
|
-
| `prop` | `DynamicValue` | `{ status: "available", value }` |
|
|
279
|
-
| `editable_prop` | `EditableValue` | `{ status: "available", value, displayValue, readOnly: false, setValue, ... }` |
|
|
280
|
-
| `action_prop` | `ActionValue` | `{ canExecute: true, isExecuting: false, execute }` |
|
|
281
|
-
|
|
282
|
-
### 컴포넌트 렌더링
|
|
283
|
-
|
|
284
|
-
```gleam
|
|
285
|
-
import mendraw/interop
|
|
286
|
-
import mendraw/widget
|
|
287
|
-
import redraw/dom/attribute
|
|
288
|
-
|
|
289
|
-
let comp = widget.component("Switch")
|
|
290
|
-
|
|
291
|
-
// 속성 + 자식 엘리먼트
|
|
292
|
-
interop.component_el(comp, [
|
|
293
|
-
widget.prop("caption", "제목"),
|
|
294
|
-
widget.editable_prop("textAttr", value, "표시값", set_value),
|
|
295
|
-
widget.action_prop("onClick", handler),
|
|
296
|
-
], [])
|
|
297
|
-
|
|
298
|
-
// 속성 없이 자식만
|
|
299
|
-
interop.component_el_(comp, [child1, child2])
|
|
300
|
-
|
|
301
|
-
// 자식 없는 self-closing 컴포넌트
|
|
302
|
-
interop.void_component_el(comp, [
|
|
303
|
-
widget.prop("caption", "읽기 전용"),
|
|
304
|
-
])
|
|
305
|
-
```
|
|
123
|
+
## Classic (Dojo) 위젯
|
|
306
124
|
|
|
307
125
|
### Classic 위젯 직접 렌더링
|
|
308
126
|
|
|
@@ -395,118 +213,6 @@ let js_value = mendix.from_option(gleam_option)
|
|
|
395
213
|
|
|
396
214
|
---
|
|
397
215
|
|
|
398
|
-
## 생성된 코드 구조
|
|
399
|
-
|
|
400
|
-
### Pluggable 위젯 바인딩 예시
|
|
401
|
-
|
|
402
|
-
Switch 위젯에서 생성되는 `src/widgets/switch.gleam`:
|
|
403
|
-
|
|
404
|
-
```gleam
|
|
405
|
-
// @generated mendraw/install — 직접 수정 금지
|
|
406
|
-
|
|
407
|
-
import gleam/option.{None, Some}
|
|
408
|
-
import mendraw/interop
|
|
409
|
-
import mendraw/mendix.{type JsProps}
|
|
410
|
-
import mendraw/widget
|
|
411
|
-
import redraw.{type Element}
|
|
412
|
-
import redraw/dom/attribute
|
|
413
|
-
|
|
414
|
-
pub fn render(props: JsProps) -> Element {
|
|
415
|
-
// 필수 속성
|
|
416
|
-
let text_attr = mendix.get_prop_required(props, "textAttr")
|
|
417
|
-
// 선택 속성
|
|
418
|
-
let caption = mendix.get_prop(props, "caption")
|
|
419
|
-
|
|
420
|
-
let comp = widget.component("Switch")
|
|
421
|
-
interop.component_el(
|
|
422
|
-
comp,
|
|
423
|
-
[
|
|
424
|
-
attribute.attribute("textAttr", text_attr),
|
|
425
|
-
// 선택 속성은 있을 때만 전달
|
|
426
|
-
..optional_attr("caption", caption)
|
|
427
|
-
],
|
|
428
|
-
[],
|
|
429
|
-
)
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
fn optional_attr(key: String, value: option.Option(a)) -> List(attribute.Attribute) {
|
|
433
|
-
case value {
|
|
434
|
-
Some(v) -> [attribute.attribute(key, v)]
|
|
435
|
-
None -> []
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
### Classic 위젯 바인딩 예시
|
|
441
|
-
|
|
442
|
-
CameraWidget 위젯에서 생성되는 `src/widgets/camera_widget.gleam`:
|
|
443
|
-
|
|
444
|
-
```gleam
|
|
445
|
-
// @generated mendraw/install — 직접 수정 금지
|
|
446
|
-
|
|
447
|
-
import gleam/option.{None, Some}
|
|
448
|
-
import mendraw/classic
|
|
449
|
-
import mendraw/mendix.{type JsProps}
|
|
450
|
-
import redraw.{type Element}
|
|
451
|
-
|
|
452
|
-
pub fn render(props: JsProps) -> Element {
|
|
453
|
-
let mf_to_execute = mendix.get_prop_required(props, "mfToExecute")
|
|
454
|
-
let prefer_rear_camera = mendix.get_prop_required(props, "preferRearCamera")
|
|
455
|
-
|
|
456
|
-
classic.render("CameraWidget.widget.CameraWidget", [
|
|
457
|
-
#("mfToExecute", classic.to_dynamic(mf_to_execute)),
|
|
458
|
-
#("preferRearCamera", classic.to_dynamic(prefer_rear_camera)),
|
|
459
|
-
])
|
|
460
|
-
}
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
### 파일명 변환 규칙
|
|
464
|
-
|
|
465
|
-
위젯 이름은 Gleam 모듈명 규칙에 맞게 snake_case로 변환된다:
|
|
466
|
-
|
|
467
|
-
| 위젯 이름 | 파일명 | 모듈 경로 |
|
|
468
|
-
|-----------|--------|----------|
|
|
469
|
-
| `Switch` | `switch.gleam` | `widgets/switch` |
|
|
470
|
-
| `AreaChart` | `area_chart.gleam` | `widgets/area_chart` |
|
|
471
|
-
| `BarChart` | `bar_chart.gleam` | `widgets/bar_chart` |
|
|
472
|
-
| `CameraWidget` | `camera_widget.gleam` | `widgets/camera_widget` |
|
|
473
|
-
| `Progress Bar` | `progress_bar.gleam` | `widgets/progress_bar` |
|
|
474
|
-
|
|
475
|
-
---
|
|
476
|
-
|
|
477
|
-
## 생성된 바인딩 커스터마이징
|
|
478
|
-
|
|
479
|
-
생성된 `src/widgets/*.gleam` 파일은 한 번 생성된 후 **덮어쓰지 않는다**.
|
|
480
|
-
따라서 생성된 파일을 직접 수정하여 커스터마이징할 수 있다:
|
|
481
|
-
|
|
482
|
-
```gleam
|
|
483
|
-
// src/widgets/switch.gleam — 사용자가 수정한 버전
|
|
484
|
-
import mendraw/interop
|
|
485
|
-
import mendraw/mendix.{type JsProps}
|
|
486
|
-
import mendraw/widget
|
|
487
|
-
import redraw.{type Element}
|
|
488
|
-
import redraw/dom/attribute
|
|
489
|
-
|
|
490
|
-
pub fn render(props: JsProps) -> Element {
|
|
491
|
-
let text_attr = mendix.get_prop_required(props, "textAttr")
|
|
492
|
-
let comp = widget.component("Switch")
|
|
493
|
-
interop.component_el(
|
|
494
|
-
comp,
|
|
495
|
-
[
|
|
496
|
-
widget.editable_prop("textAttr", text_attr, "표시값", fn(v) { Nil }),
|
|
497
|
-
// 커스텀: 고정 캡션 추가
|
|
498
|
-
widget.prop("caption", "내 스위치"),
|
|
499
|
-
],
|
|
500
|
-
[],
|
|
501
|
-
)
|
|
502
|
-
}
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
> **주의**: 수정한 파일은 `gleam run -m mendraw/install`을 다시 실행해도 덮어쓰지 않는다.
|
|
506
|
-
> 바인딩을 재생성하려면 해당 파일을 삭제한 후 install을 다시 실행한다.
|
|
507
|
-
|
|
508
|
-
---
|
|
509
|
-
|
|
510
216
|
## API 레퍼런스
|
|
511
217
|
|
|
512
218
|
### mendraw/mendix
|
|
@@ -535,17 +241,6 @@ Mendix Pluggable Widget API의 핵심 타입과 props 접근자.
|
|
|
535
241
|
| `to_option` | `(a) -> Option(a)` | JS undefined/null → `None` |
|
|
536
242
|
| `from_option` | `(Option(a)) -> a` | Gleam `Option` → JS 값 (`None` → undefined) |
|
|
537
243
|
|
|
538
|
-
### mendraw/widget
|
|
539
|
-
|
|
540
|
-
Pluggable 위젯 컴포넌트 조회 및 prop 래핑.
|
|
541
|
-
|
|
542
|
-
| 함수 | 시그니처 | 설명 |
|
|
543
|
-
|------|----------|------|
|
|
544
|
-
| `component` | `(String) -> JsComponent` | 이름으로 위젯 컴포넌트 조회 |
|
|
545
|
-
| `prop` | `(String, a) -> Attribute` | `DynamicValue`로 래핑 (읽기 전용) |
|
|
546
|
-
| `editable_prop` | `(String, a, String, fn(a) -> Nil) -> Attribute` | `EditableValue`로 래핑 (편집 가능) |
|
|
547
|
-
| `action_prop` | `(String, fn() -> Nil) -> Attribute` | `ActionValue`로 래핑 (이벤트 핸들러) |
|
|
548
|
-
|
|
549
244
|
### mendraw/interop
|
|
550
245
|
|
|
551
246
|
외부 JS React 컴포넌트를 redraw Element로 변환하는 브릿지.
|
|
@@ -579,10 +274,8 @@ Classic (Dojo) 위젯을 React 내부에서 렌더링.
|
|
|
579
274
|
| 함수 | 시그니처 | 설명 |
|
|
580
275
|
|------|----------|------|
|
|
581
276
|
| `file_exists` | `(String) -> Bool` | 파일 존재 여부 |
|
|
582
|
-
| `
|
|
583
|
-
| `resolve_toml_widgets` | `() -> Nil` | gleam.toml [tools.mendraw.widgets.*] 다운로드/캐시 |
|
|
277
|
+
| `resolve_toml_widgets` | `() -> Nil` | gleam.toml [tools.mendraw.widgets.*] 다운로드 |
|
|
584
278
|
| `write_widget_toml` | `(String, String, Option(Int), Option(String)) -> Nil` | gleam.toml에 위젯 항목 쓰기 |
|
|
585
|
-
| `download_to_cache` | `(String, String, String, Option(Int)) -> Bool` | URL에서 build/widgets/{name}/에 다운로드+추출 |
|
|
586
279
|
|
|
587
280
|
### mendraw/marketplace
|
|
588
281
|
|
|
@@ -596,8 +289,6 @@ Mendix Marketplace 위젯 검색·다운로드 TUI. `gleam run -m mendraw/market
|
|
|
596
289
|
| 백그라운드 로딩 | 전체 위젯 목록을 백그라운드에서 점진적으로 로드 |
|
|
597
290
|
| 버전 선택 | Content API + chrobot_extra 사이드카(XAS)로 버전별 다운로드 정보 조회 |
|
|
598
291
|
| 자동 TOML 기록 | 다운로드 시 gleam.toml에 위젯 항목 자동 추가 |
|
|
599
|
-
| 캐시 다운로드 | build/widgets/에 캐시 (소스 컨트롤에 .mpk 불필요) |
|
|
600
|
-
| 자동 바인딩 | 다운로드 완료 후 `generate_widget_bindings()` 자동 호출 |
|
|
601
292
|
|
|
602
293
|
#### 의존성
|
|
603
294
|
|
|
@@ -610,7 +301,7 @@ Mendix Marketplace 위젯 검색·다운로드 TUI. `gleam run -m mendraw/market
|
|
|
610
301
|
## glendix 프로젝트에서 사용하기
|
|
611
302
|
|
|
612
303
|
[glendix](https://github.com/) 프로젝트에서 mendraw를 의존성으로 추가하면,
|
|
613
|
-
|
|
304
|
+
위젯 TOML 해석을 mendraw에 위임할 수 있다:
|
|
614
305
|
|
|
615
306
|
```gleam
|
|
616
307
|
// glendix의 install.gleam
|
|
@@ -619,8 +310,7 @@ import mendraw/cmd as mendraw_cmd
|
|
|
619
310
|
pub fn main() {
|
|
620
311
|
cmd.exec(cmd.detect_install_command())
|
|
621
312
|
cmd.generate_bindings()
|
|
622
|
-
|
|
623
|
-
mendraw_cmd.generate_widget_bindings()
|
|
313
|
+
mendraw_cmd.resolve_toml_widgets()
|
|
624
314
|
}
|
|
625
315
|
```
|
|
626
316
|
|
|
@@ -628,44 +318,11 @@ pub fn main() {
|
|
|
628
318
|
|
|
629
319
|
## 문제 해결
|
|
630
320
|
|
|
631
|
-
### `gleam run -m mendraw/install` 실행 시 아무것도 생성되지 않는다
|
|
632
|
-
|
|
633
|
-
- `gleam.toml`에 `[tools.mendraw.widgets.*]` 섹션이 있는지 확인
|
|
634
|
-
- `.mpk` 파일이 유효한 ZIP 형식인지 확인
|
|
635
|
-
- 콘솔 출력을 확인하여 파싱 오류가 없는지 점검
|
|
636
|
-
|
|
637
|
-
### 이미 존재하는 바인딩 파일이 업데이트되지 않는다
|
|
638
|
-
|
|
639
|
-
mendraw는 `src/widgets/`에 이미 존재하는 `.gleam` 파일을 **덮어쓰지 않는다** (사용자 수정 보호).
|
|
640
|
-
바인딩을 재생성하려면:
|
|
641
|
-
|
|
642
|
-
```sh
|
|
643
|
-
# 특정 파일만 재생성
|
|
644
|
-
rm src/widgets/switch.gleam
|
|
645
|
-
gleam run -m mendraw/install
|
|
646
|
-
|
|
647
|
-
# 전체 재생성
|
|
648
|
-
rm src/widgets/*.gleam
|
|
649
|
-
gleam run -m mendraw/install
|
|
650
|
-
```
|
|
651
|
-
|
|
652
|
-
### "widget_ffi.mjs not generated" 에러
|
|
653
|
-
|
|
654
|
-
`widget_ffi.mjs`와 `classic_ffi.mjs`는 스텁 파일로 시작한다.
|
|
655
|
-
`gleam run -m mendraw/install`을 실행하면 빌드 경로에 실제 파일이 생성된다.
|
|
656
|
-
install을 실행하지 않고 위젯 모듈을 import하면 이 에러가 발생한다.
|
|
657
|
-
|
|
658
321
|
### Classic 위젯이 렌더링되지 않는다
|
|
659
322
|
|
|
660
323
|
- Classic 위젯은 DOM 컨테이너를 생성하고 imperative하게 마운트한다
|
|
661
324
|
- `classic_ffi.mjs`가 빌드 경로에 정상적으로 생성되었는지 확인
|
|
662
325
|
- `widget_id`가 정확한지 확인 (예: `"CameraWidget.widget.CameraWidget"`)
|
|
663
326
|
|
|
664
|
-
### Pluggable 위젯과 Classic 위젯을 구분하는 기준
|
|
665
|
-
|
|
666
|
-
mendraw는 `.mpk` 파일 내부의 구조로 자동 판별한다:
|
|
667
|
-
|
|
668
|
-
- `.mjs` 파일이 포함되어 있으면 → **Pluggable** 위젯
|
|
669
|
-
- `.mjs` 없이 `.js`만 포함되어 있으면 → **Classic** 위젯
|
|
670
327
|
|
|
671
328
|
사용자가 별도로 지정할 필요 없다.
|
package/template/gleam.toml
CHANGED
|
@@ -8,8 +8,8 @@ runtime = "node"
|
|
|
8
8
|
|
|
9
9
|
[dependencies]
|
|
10
10
|
gleam_stdlib = ">= 0.44.0 and < 2.0.0"
|
|
11
|
-
glendix = ">= 4.0.
|
|
12
|
-
mendraw = ">= 1.1.
|
|
11
|
+
glendix = ">= 4.0.3 and < 5.0.0"
|
|
12
|
+
mendraw = ">= 1.1.11 and < 2.0.0"
|
|
13
13
|
dee = ">= 1.0.0 and < 2.0.0"
|
|
14
14
|
redraw = ">= 19.2.2 and < 20.0.0"
|
|
15
15
|
redraw_dom = ">= 19.2.2 and < 20.0.0"
|
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* widgets/README.md template — 3 language versions
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export function generateWidgetsReadmeContent(lang) {
|
|
6
|
-
switch (lang) {
|
|
7
|
-
case "ko":
|
|
8
|
-
return generateKo();
|
|
9
|
-
case "ja":
|
|
10
|
-
return generateJa();
|
|
11
|
-
default:
|
|
12
|
-
return generateEn();
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function generateEn() {
|
|
17
|
-
return `# widgets/
|
|
18
|
-
|
|
19
|
-
Mendix widget binding directory. Place \`.mpk\` files (Mendix widget build artifacts) in this directory to render existing Mendix widgets as React components from Gleam code.
|
|
20
|
-
|
|
21
|
-
## Usage
|
|
22
|
-
|
|
23
|
-
### 1. Place \`.mpk\` files
|
|
24
|
-
|
|
25
|
-
Copy built Mendix widget \`.mpk\` files into this directory:
|
|
26
|
-
|
|
27
|
-
\`\`\`
|
|
28
|
-
widgets/
|
|
29
|
-
├── Switch.mpk
|
|
30
|
-
├── Badge.mpk
|
|
31
|
-
└── README.md
|
|
32
|
-
\`\`\`
|
|
33
|
-
|
|
34
|
-
### 2. Generate bindings
|
|
35
|
-
|
|
36
|
-
\`\`\`bash
|
|
37
|
-
gleam run -m glendix/install
|
|
38
|
-
\`\`\`
|
|
39
|
-
|
|
40
|
-
This automatically:
|
|
41
|
-
|
|
42
|
-
- Extracts \`.mjs\` and \`.css\` from \`.mpk\` and generates \`widget_ffi.mjs\`
|
|
43
|
-
- Parses \`<property>\` definitions from \`.mpk\` XML and generates binding \`.gleam\` files in \`src/widgets/\` (existing files are skipped)
|
|
44
|
-
|
|
45
|
-
### 3. Review auto-generated bindings
|
|
46
|
-
|
|
47
|
-
For example, placing \`Switch.mpk\` generates \`src/widgets/switch.gleam\`:
|
|
48
|
-
|
|
49
|
-
\`\`\`gleam
|
|
50
|
-
// src/widgets/switch.gleam (auto-generated)
|
|
51
|
-
import mendraw/interop
|
|
52
|
-
import mendraw/mendix.{type JsProps}
|
|
53
|
-
import mendraw/widget
|
|
54
|
-
import redraw.{type Element}
|
|
55
|
-
import redraw/dom/attribute
|
|
56
|
-
|
|
57
|
-
/// Render Switch widget - reads properties from props and passes them to the widget
|
|
58
|
-
pub fn render(props: JsProps) -> Element {
|
|
59
|
-
let boolean_attribute = mendix.get_prop_required(props, "booleanAttribute")
|
|
60
|
-
let action = mendix.get_prop_required(props, "action")
|
|
61
|
-
|
|
62
|
-
let comp = widget.component("Switch")
|
|
63
|
-
interop.component_el(
|
|
64
|
-
comp,
|
|
65
|
-
[
|
|
66
|
-
attribute.attribute("booleanAttribute", boolean_attribute),
|
|
67
|
-
attribute.attribute("action", action),
|
|
68
|
-
],
|
|
69
|
-
[],
|
|
70
|
-
)
|
|
71
|
-
}
|
|
72
|
-
\`\`\`
|
|
73
|
-
|
|
74
|
-
- Required/optional properties are distinguished automatically
|
|
75
|
-
- If optional properties exist, \`optional_attr\` helper and \`gleam/option\` import are added automatically
|
|
76
|
-
- Gleam reserved words (e.g. \`type\`) are automatically suffixed with \`_\`
|
|
77
|
-
- Generated files can be freely modified as needed
|
|
78
|
-
|
|
79
|
-
### 4. Use from Gleam
|
|
80
|
-
|
|
81
|
-
\`\`\`gleam
|
|
82
|
-
import widgets/switch
|
|
83
|
-
|
|
84
|
-
// Inside a component
|
|
85
|
-
switch.render(props)
|
|
86
|
-
\`\`\`
|
|
87
|
-
|
|
88
|
-
## How it works
|
|
89
|
-
|
|
90
|
-
- \`mendraw/widget\` module's \`widget.component("Name")\` imports \`.mpk\` widgets as React components
|
|
91
|
-
- Props are passed via the generic \`attribute.attribute(key, value)\` function
|
|
92
|
-
- Widget names use the \`<name>\` value from the \`.mpk\`'s internal XML, and property keys use the original keys from the \`.mpk\` XML
|
|
93
|
-
- Unlike the \`binding\` module, 1 mpk = 1 component, so \`widget.component("Name")\` imports it in one call
|
|
94
|
-
|
|
95
|
-
## Notes
|
|
96
|
-
|
|
97
|
-
- After adding/removing \`.mpk\` files, you must run \`gleam run -m glendix/install\` again
|
|
98
|
-
- \`widget_ffi.mjs\` is auto-generated — do not edit it directly
|
|
99
|
-
- Do not write \`.mjs\` FFI files for \`.mpk\` widgets manually — use the \`widgets/\` directory + \`mendraw/widget\`
|
|
100
|
-
`;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function generateKo() {
|
|
104
|
-
return `# widgets/
|
|
105
|
-
|
|
106
|
-
Mendix 위젯 바인딩 디렉토리. \`.mpk\` 파일(Mendix 위젯 빌드 결과물)을 이 디렉토리에 배치하면, Gleam 코드에서 기존 Mendix 위젯을 React 컴포넌트로 렌더링할 수 있다.
|
|
107
|
-
|
|
108
|
-
## 사용법
|
|
109
|
-
|
|
110
|
-
### 1. \`.mpk\` 파일 배치
|
|
111
|
-
|
|
112
|
-
빌드된 Mendix 위젯의 \`.mpk\` 파일을 이 디렉토리에 복사한다:
|
|
113
|
-
|
|
114
|
-
\`\`\`
|
|
115
|
-
widgets/
|
|
116
|
-
├── Switch.mpk
|
|
117
|
-
├── Badge.mpk
|
|
118
|
-
└── README.md
|
|
119
|
-
\`\`\`
|
|
120
|
-
|
|
121
|
-
### 2. 바인딩 생성
|
|
122
|
-
|
|
123
|
-
\`\`\`bash
|
|
124
|
-
gleam run -m glendix/install
|
|
125
|
-
\`\`\`
|
|
126
|
-
|
|
127
|
-
실행 시 다음이 자동 처리된다:
|
|
128
|
-
|
|
129
|
-
- \`.mpk\` 내부의 \`.mjs\`와 \`.css\`가 추출되고, \`widget_ffi.mjs\`가 생성된다
|
|
130
|
-
- \`.mpk\` XML의 \`<property>\` 정의를 파싱하여 \`src/widgets/\`에 바인딩 \`.gleam\` 파일이 자동 생성된다 (이미 존재하면 건너뜀)
|
|
131
|
-
|
|
132
|
-
### 3. 자동 생성된 바인딩 확인
|
|
133
|
-
|
|
134
|
-
예를 들어 \`Switch.mpk\`를 배치하면 \`src/widgets/switch.gleam\`이 생성된다:
|
|
135
|
-
|
|
136
|
-
\`\`\`gleam
|
|
137
|
-
// src/widgets/switch.gleam (자동 생성)
|
|
138
|
-
import mendraw/interop
|
|
139
|
-
import mendraw/mendix.{type JsProps}
|
|
140
|
-
import mendraw/widget
|
|
141
|
-
import redraw.{type Element}
|
|
142
|
-
import redraw/dom/attribute
|
|
143
|
-
|
|
144
|
-
/// Switch 위젯 렌더링 - props에서 속성을 읽어 위젯에 전달
|
|
145
|
-
pub fn render(props: JsProps) -> Element {
|
|
146
|
-
let boolean_attribute = mendix.get_prop_required(props, "booleanAttribute")
|
|
147
|
-
let action = mendix.get_prop_required(props, "action")
|
|
148
|
-
|
|
149
|
-
let comp = widget.component("Switch")
|
|
150
|
-
interop.component_el(
|
|
151
|
-
comp,
|
|
152
|
-
[
|
|
153
|
-
attribute.attribute("booleanAttribute", boolean_attribute),
|
|
154
|
-
attribute.attribute("action", action),
|
|
155
|
-
],
|
|
156
|
-
[],
|
|
157
|
-
)
|
|
158
|
-
}
|
|
159
|
-
\`\`\`
|
|
160
|
-
|
|
161
|
-
- required/optional 속성이 자동 구분된다
|
|
162
|
-
- optional 속성이 있으면 \`optional_attr\` 헬퍼와 \`gleam/option\` import가 자동 추가된다
|
|
163
|
-
- Gleam 예약어(\`type\` 등)는 접미사 \`_\`로 자동 회피된다
|
|
164
|
-
- 생성된 파일은 필요에 따라 자유롭게 수정 가능하다
|
|
165
|
-
|
|
166
|
-
### 4. Gleam에서 사용
|
|
167
|
-
|
|
168
|
-
\`\`\`gleam
|
|
169
|
-
import widgets/switch
|
|
170
|
-
|
|
171
|
-
// 컴포넌트 내부에서
|
|
172
|
-
switch.render(props)
|
|
173
|
-
\`\`\`
|
|
174
|
-
|
|
175
|
-
## 동작 원리
|
|
176
|
-
|
|
177
|
-
- \`mendraw/widget\` 모듈의 \`widget.component("Name")\`으로 \`.mpk\` 위젯을 React 컴포넌트로 가져온다
|
|
178
|
-
- Props는 \`attribute.attribute(key, value)\` 범용 함수로 전달한다
|
|
179
|
-
- 위젯 이름은 \`.mpk\` 내부 XML의 \`<name>\` 값을, property key는 XML의 원본 key를 그대로 사용한다
|
|
180
|
-
- \`binding\` 모듈과 달리 1 mpk = 1 컴포넌트이므로 \`widget.component("Name")\` 한 번에 가져온다
|
|
181
|
-
|
|
182
|
-
## 주의사항
|
|
183
|
-
|
|
184
|
-
- \`.mpk\` 파일을 추가/제거한 후에는 반드시 \`gleam run -m glendix/install\`을 다시 실행해야 한다
|
|
185
|
-
- \`widget_ffi.mjs\`는 자동 생성 파일이므로 직접 수정하지 않는다
|
|
186
|
-
- \`.mpk\` 위젯용 \`.mjs\` FFI 파일을 직접 작성하지 않는다 — \`widgets/\` 디렉토리 + \`mendraw/widget\`을 사용한다
|
|
187
|
-
`;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function generateJa() {
|
|
191
|
-
return `# widgets/
|
|
192
|
-
|
|
193
|
-
Mendixウィジェットバインディングディレクトリ。\`.mpk\`ファイル(Mendixウィジェットビルド成果物)をこのディレクトリに配置すると、Gleamコードから既存のMendixウィジェットをReactコンポーネントとしてレンダリングできる。
|
|
194
|
-
|
|
195
|
-
## 使い方
|
|
196
|
-
|
|
197
|
-
### 1. \`.mpk\`ファイルの配置
|
|
198
|
-
|
|
199
|
-
ビルド済みMendixウィジェットの\`.mpk\`ファイルをこのディレクトリにコピーする:
|
|
200
|
-
|
|
201
|
-
\`\`\`
|
|
202
|
-
widgets/
|
|
203
|
-
├── Switch.mpk
|
|
204
|
-
├── Badge.mpk
|
|
205
|
-
└── README.md
|
|
206
|
-
\`\`\`
|
|
207
|
-
|
|
208
|
-
### 2. バインディングの生成
|
|
209
|
-
|
|
210
|
-
\`\`\`bash
|
|
211
|
-
gleam run -m glendix/install
|
|
212
|
-
\`\`\`
|
|
213
|
-
|
|
214
|
-
実行時に以下が自動処理される:
|
|
215
|
-
|
|
216
|
-
- \`.mpk\`内部の\`.mjs\`と\`.css\`が抽出され、\`widget_ffi.mjs\`が生成される
|
|
217
|
-
- \`.mpk\` XMLの\`<property>\`定義をパースし、\`src/widgets/\`にバインディング\`.gleam\`ファイルが自動生成される(既存ファイルはスキップ)
|
|
218
|
-
|
|
219
|
-
### 3. 自動生成されたバインディングの確認
|
|
220
|
-
|
|
221
|
-
例えば\`Switch.mpk\`を配置すると\`src/widgets/switch.gleam\`が生成される:
|
|
222
|
-
|
|
223
|
-
\`\`\`gleam
|
|
224
|
-
// src/widgets/switch.gleam(自動生成)
|
|
225
|
-
import mendraw/interop
|
|
226
|
-
import mendraw/mendix.{type JsProps}
|
|
227
|
-
import mendraw/widget
|
|
228
|
-
import redraw.{type Element}
|
|
229
|
-
import redraw/dom/attribute
|
|
230
|
-
|
|
231
|
-
/// Switchウィジェットのレンダリング - propsからプロパティを読み取りウィジェットに渡す
|
|
232
|
-
pub fn render(props: JsProps) -> Element {
|
|
233
|
-
let boolean_attribute = mendix.get_prop_required(props, "booleanAttribute")
|
|
234
|
-
let action = mendix.get_prop_required(props, "action")
|
|
235
|
-
|
|
236
|
-
let comp = widget.component("Switch")
|
|
237
|
-
interop.component_el(
|
|
238
|
-
comp,
|
|
239
|
-
[
|
|
240
|
-
attribute.attribute("booleanAttribute", boolean_attribute),
|
|
241
|
-
attribute.attribute("action", action),
|
|
242
|
-
],
|
|
243
|
-
[],
|
|
244
|
-
)
|
|
245
|
-
}
|
|
246
|
-
\`\`\`
|
|
247
|
-
|
|
248
|
-
- required/optionalプロパティは自動的に区別される
|
|
249
|
-
- optionalプロパティがある場合、\`optional_attr\`ヘルパーと\`gleam/option\` importが自動追加される
|
|
250
|
-
- Gleam予約語(\`type\`等)はサフィックス\`_\`で自動回避される
|
|
251
|
-
- 生成されたファイルは必要に応じて自由に編集できる
|
|
252
|
-
|
|
253
|
-
### 4. Gleamから使用
|
|
254
|
-
|
|
255
|
-
\`\`\`gleam
|
|
256
|
-
import widgets/switch
|
|
257
|
-
|
|
258
|
-
// コンポーネント内で
|
|
259
|
-
switch.render(props)
|
|
260
|
-
\`\`\`
|
|
261
|
-
|
|
262
|
-
## 仕組み
|
|
263
|
-
|
|
264
|
-
- \`mendraw/widget\`モジュールの\`widget.component("Name")\`で\`.mpk\`ウィジェットをReactコンポーネントとしてインポートする
|
|
265
|
-
- Propsは\`attribute.attribute(key, value)\`汎用関数で渡す
|
|
266
|
-
- ウィジェット名は\`.mpk\`内部XMLの\`<name>\`値を、プロパティキーはXMLの元のキーをそのまま使用する
|
|
267
|
-
- \`binding\`モジュールと異なり1 mpk = 1コンポーネントなので、\`widget.component("Name")\`で一度にインポートする
|
|
268
|
-
|
|
269
|
-
## 注意事項
|
|
270
|
-
|
|
271
|
-
- \`.mpk\`ファイルを追加/削除した後は必ず\`gleam run -m glendix/install\`を再実行すること
|
|
272
|
-
- \`widget_ffi.mjs\`は自動生成ファイルなので直接編集しない
|
|
273
|
-
- \`.mpk\`ウィジェット用の\`.mjs\` FFIファイルを直接記述しない — \`widgets/\`ディレクトリ + \`mendraw/widget\`を使用する
|
|
274
|
-
`;
|
|
275
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{{I18N:widgets_readme}}
|