create-mendix-widget-gleam 1.0.2 → 1.0.4
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 +61 -0
- package/package.json +3 -2
- package/src/index.mjs +2 -0
- package/template/src/widget/mendix/big.gleam +86 -0
- package/template/src/widget/mendix/date.gleam +92 -0
- package/template/src/widget/mendix/editable_value.gleam +1 -1
- package/template/src/widget/mendix/reference.gleam +4 -4
- package/template/src/widget/mendix_ffi.mjs +157 -0
- package/template/src/widget/react/hook.gleam +18 -0
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# create-mendix-widget-gleam
|
|
2
|
+
|
|
3
|
+
Gleam 언어로 Mendix Pluggable Widget 프로젝트를 스케폴딩하는 CLI 도구.
|
|
4
|
+
|
|
5
|
+
JSX 없이, **오직 Gleam + FFI**로 React 컴포넌트를 작성하여 Mendix Studio Pro에서 동작하는 위젯을 만든다.
|
|
6
|
+
|
|
7
|
+
## 사용법
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx create-mendix-widget-gleam my-widget
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
대화형 프롬프트를 통해 프로젝트명과 패키지 매니저를 선택하면, 즉시 개발 가능한 위젯 프로젝트가 생성된다.
|
|
14
|
+
|
|
15
|
+
## 사전 요구사항
|
|
16
|
+
|
|
17
|
+
- [Gleam](https://gleam.run/getting-started/installing/) (최신 버전)
|
|
18
|
+
- [Node.js](https://nodejs.org/) (v18+)
|
|
19
|
+
|
|
20
|
+
## 생성되는 프로젝트 구조
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
my-widget/
|
|
24
|
+
src/
|
|
25
|
+
widget/ # Gleam 위젯 코드
|
|
26
|
+
my_widget.gleam # 메인 위젯 모듈
|
|
27
|
+
react_ffi.mjs # React FFI 어댑터
|
|
28
|
+
mendix_ffi.mjs # Mendix FFI 어댑터
|
|
29
|
+
react.gleam + react/ # React 바인딩 (타입, Props, Hooks, HTML)
|
|
30
|
+
mendix.gleam + mendix/ # Mendix API 바인딩 (전체 Pluggable Widget API)
|
|
31
|
+
editor_config.gleam # Studio Pro 속성 패널
|
|
32
|
+
scripts/ # 빌드/개발 스크립트
|
|
33
|
+
gleam.toml # Gleam 프로젝트 설정
|
|
34
|
+
CLAUDE.md # AI 어시스턴트용 프로젝트 컨텍스트
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 생성 후 시작하기
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cd my-widget
|
|
41
|
+
gleam run -m scripts/install # 의존성 설치
|
|
42
|
+
gleam run -m scripts/dev # 개발 서버 시작
|
|
43
|
+
gleam run -m scripts/build # 프로덕션 빌드 (.mpk 생성)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 포함된 Mendix API 바인딩
|
|
47
|
+
|
|
48
|
+
생성된 프로젝트에는 Mendix Pluggable Widget API 전체에 대한 Gleam 바인딩이 포함되어 있다:
|
|
49
|
+
|
|
50
|
+
- **EditableValue** — 텍스트, 숫자, 날짜 등 편집 가능한 값
|
|
51
|
+
- **ActionValue** — 마이크로플로우/나노플로우 실행
|
|
52
|
+
- **ListValue** — 데이터 목록 (필터, 정렬, 페이지네이션)
|
|
53
|
+
- **SelectionValue** — 단일/다중 선택
|
|
54
|
+
- **ReferenceValue** — 연관 관계 (단일/다중 참조)
|
|
55
|
+
- **JsDate / Big** — JS Date, Big.js 고정밀 십진수 래퍼
|
|
56
|
+
- **Filter** — 필터 조건 빌더
|
|
57
|
+
- **그 외** — DynamicValue, FileValue, WebIcon, ValueFormatter 등
|
|
58
|
+
|
|
59
|
+
## 라이선스
|
|
60
|
+
|
|
61
|
+
Apache-2.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-mendix-widget-gleam",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Scaffold a Mendix Pluggable Widget powered by Gleam",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"bin/",
|
|
10
10
|
"src/",
|
|
11
|
-
"template/"
|
|
11
|
+
"template/",
|
|
12
|
+
"README.md"
|
|
12
13
|
],
|
|
13
14
|
"engines": {
|
|
14
15
|
"node": ">=18"
|
package/src/index.mjs
CHANGED
|
@@ -214,6 +214,8 @@ gleam format # Gleam 코드 포맷팅
|
|
|
214
214
|
- \`mendix/list_attribute.gleam\` — \`ListAttributeValue\` 등 리스트 연결 타입
|
|
215
215
|
- \`mendix/selection.gleam\` — 단일/다중 선택
|
|
216
216
|
- \`mendix/reference.gleam\` — 참조 관계 값
|
|
217
|
+
- \`mendix/date.gleam\` — \`JsDate\` (JS Date opaque 래퍼)
|
|
218
|
+
- \`mendix/big.gleam\` — \`Big\` (Big.js 고정밀 십진수 래퍼)
|
|
217
219
|
- \`mendix/file.gleam\` — 파일/이미지
|
|
218
220
|
- \`mendix/icon.gleam\` — 아이콘
|
|
219
221
|
- \`mendix/formatter.gleam\` — 값 포맷팅/파싱
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Mendix Big.js 타입 — 고정밀 십진수 Gleam opaque 래퍼
|
|
2
|
+
// EditableValue<BigJs.Big>에서 반환되는 Big.js 객체를 타입 안전하게 다룸
|
|
3
|
+
|
|
4
|
+
import gleam/order.{type Order, Eq, Gt, Lt}
|
|
5
|
+
|
|
6
|
+
// === 타입 ===
|
|
7
|
+
|
|
8
|
+
pub type Big
|
|
9
|
+
|
|
10
|
+
// === 생성 ===
|
|
11
|
+
|
|
12
|
+
/// 문자열로 Big 생성
|
|
13
|
+
@external(javascript, "../mendix_ffi.mjs", "big_from_string")
|
|
14
|
+
pub fn from_string(s: String) -> Big
|
|
15
|
+
|
|
16
|
+
/// 정수로 Big 생성
|
|
17
|
+
@external(javascript, "../mendix_ffi.mjs", "big_from_int")
|
|
18
|
+
pub fn from_int(n: Int) -> Big
|
|
19
|
+
|
|
20
|
+
/// 부동소수점으로 Big 생성
|
|
21
|
+
@external(javascript, "../mendix_ffi.mjs", "big_from_float")
|
|
22
|
+
pub fn from_float(f: Float) -> Big
|
|
23
|
+
|
|
24
|
+
// === 변환 ===
|
|
25
|
+
|
|
26
|
+
/// 문자열로 변환
|
|
27
|
+
@external(javascript, "../mendix_ffi.mjs", "big_to_string")
|
|
28
|
+
pub fn to_string(b: Big) -> String
|
|
29
|
+
|
|
30
|
+
/// Float로 변환 (정밀도 손실 가능)
|
|
31
|
+
@external(javascript, "../mendix_ffi.mjs", "big_to_float")
|
|
32
|
+
pub fn to_float(b: Big) -> Float
|
|
33
|
+
|
|
34
|
+
/// Int로 변환 (소수점 이하 버림)
|
|
35
|
+
@external(javascript, "../mendix_ffi.mjs", "big_to_int")
|
|
36
|
+
pub fn to_int(b: Big) -> Int
|
|
37
|
+
|
|
38
|
+
/// 고정 소수점 문자열 (소수점 이하 dp자리)
|
|
39
|
+
@external(javascript, "../mendix_ffi.mjs", "big_to_fixed")
|
|
40
|
+
pub fn to_fixed(b: Big, dp: Int) -> String
|
|
41
|
+
|
|
42
|
+
// === 산술 ===
|
|
43
|
+
|
|
44
|
+
/// 덧셈
|
|
45
|
+
@external(javascript, "../mendix_ffi.mjs", "big_add")
|
|
46
|
+
pub fn add(a: Big, b: Big) -> Big
|
|
47
|
+
|
|
48
|
+
/// 뺄셈
|
|
49
|
+
@external(javascript, "../mendix_ffi.mjs", "big_sub")
|
|
50
|
+
pub fn subtract(a: Big, b: Big) -> Big
|
|
51
|
+
|
|
52
|
+
/// 곱셈
|
|
53
|
+
@external(javascript, "../mendix_ffi.mjs", "big_mul")
|
|
54
|
+
pub fn multiply(a: Big, b: Big) -> Big
|
|
55
|
+
|
|
56
|
+
/// 나눗셈
|
|
57
|
+
@external(javascript, "../mendix_ffi.mjs", "big_div")
|
|
58
|
+
pub fn divide(a: Big, b: Big) -> Big
|
|
59
|
+
|
|
60
|
+
/// 절대값
|
|
61
|
+
@external(javascript, "../mendix_ffi.mjs", "big_abs")
|
|
62
|
+
pub fn absolute(b: Big) -> Big
|
|
63
|
+
|
|
64
|
+
/// 부호 반전
|
|
65
|
+
@external(javascript, "../mendix_ffi.mjs", "big_negate")
|
|
66
|
+
pub fn negate(b: Big) -> Big
|
|
67
|
+
|
|
68
|
+
// === 비교 ===
|
|
69
|
+
|
|
70
|
+
/// 비교 (Gleam Order 반환)
|
|
71
|
+
pub fn compare(a: Big, b: Big) -> Order {
|
|
72
|
+
case cmp(a, b) {
|
|
73
|
+
x if x < 0 -> Lt
|
|
74
|
+
x if x > 0 -> Gt
|
|
75
|
+
_ -> Eq
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// 동등 비교
|
|
80
|
+
@external(javascript, "../mendix_ffi.mjs", "big_eq")
|
|
81
|
+
pub fn equal(a: Big, b: Big) -> Bool
|
|
82
|
+
|
|
83
|
+
// === 내부 FFI ===
|
|
84
|
+
|
|
85
|
+
@external(javascript, "../mendix_ffi.mjs", "big_cmp")
|
|
86
|
+
fn cmp(a: Big, b: Big) -> Int
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Mendix JS Date 타입 — Gleam opaque 래퍼
|
|
2
|
+
// EditableValue<Date>에서 반환되는 JS Date 객체를 타입 안전하게 다룸
|
|
3
|
+
|
|
4
|
+
// === 타입 ===
|
|
5
|
+
|
|
6
|
+
pub type JsDate
|
|
7
|
+
|
|
8
|
+
// === 생성 ===
|
|
9
|
+
|
|
10
|
+
/// 현재 시각
|
|
11
|
+
@external(javascript, "../mendix_ffi.mjs", "date_now")
|
|
12
|
+
pub fn now() -> JsDate
|
|
13
|
+
|
|
14
|
+
/// ISO 8601 문자열로 생성
|
|
15
|
+
@external(javascript, "../mendix_ffi.mjs", "date_from_iso")
|
|
16
|
+
pub fn from_iso(iso_string: String) -> JsDate
|
|
17
|
+
|
|
18
|
+
/// Unix 타임스탬프(밀리초)로 생성
|
|
19
|
+
@external(javascript, "../mendix_ffi.mjs", "date_from_timestamp")
|
|
20
|
+
pub fn from_timestamp(ms: Int) -> JsDate
|
|
21
|
+
|
|
22
|
+
/// 날짜/시간 요소로 생성 (month: 1-12)
|
|
23
|
+
@external(javascript, "../mendix_ffi.mjs", "date_create")
|
|
24
|
+
pub fn create(
|
|
25
|
+
year: Int,
|
|
26
|
+
month: Int,
|
|
27
|
+
day: Int,
|
|
28
|
+
hours: Int,
|
|
29
|
+
minutes: Int,
|
|
30
|
+
seconds: Int,
|
|
31
|
+
milliseconds: Int,
|
|
32
|
+
) -> JsDate
|
|
33
|
+
|
|
34
|
+
// === 변환 ===
|
|
35
|
+
|
|
36
|
+
/// ISO 8601 문자열로 변환
|
|
37
|
+
@external(javascript, "../mendix_ffi.mjs", "date_to_iso")
|
|
38
|
+
pub fn to_iso(date: JsDate) -> String
|
|
39
|
+
|
|
40
|
+
/// Unix 타임스탬프(밀리초) 반환
|
|
41
|
+
@external(javascript, "../mendix_ffi.mjs", "date_get_time")
|
|
42
|
+
pub fn to_timestamp(date: JsDate) -> Int
|
|
43
|
+
|
|
44
|
+
/// 사람이 읽기 쉬운 문자열로 변환
|
|
45
|
+
@external(javascript, "../mendix_ffi.mjs", "date_to_string")
|
|
46
|
+
pub fn to_string(date: JsDate) -> String
|
|
47
|
+
|
|
48
|
+
// === 접근자 ===
|
|
49
|
+
|
|
50
|
+
/// 연도 (4자리)
|
|
51
|
+
@external(javascript, "../mendix_ffi.mjs", "date_get_full_year")
|
|
52
|
+
pub fn year(date: JsDate) -> Int
|
|
53
|
+
|
|
54
|
+
/// 월 (1-12, Gleam 기준 1-based)
|
|
55
|
+
@external(javascript, "../mendix_ffi.mjs", "date_get_month")
|
|
56
|
+
pub fn month(date: JsDate) -> Int
|
|
57
|
+
|
|
58
|
+
/// 일 (1-31)
|
|
59
|
+
@external(javascript, "../mendix_ffi.mjs", "date_get_date")
|
|
60
|
+
pub fn day(date: JsDate) -> Int
|
|
61
|
+
|
|
62
|
+
/// 시 (0-23)
|
|
63
|
+
@external(javascript, "../mendix_ffi.mjs", "date_get_hours")
|
|
64
|
+
pub fn hours(date: JsDate) -> Int
|
|
65
|
+
|
|
66
|
+
/// 분 (0-59)
|
|
67
|
+
@external(javascript, "../mendix_ffi.mjs", "date_get_minutes")
|
|
68
|
+
pub fn minutes(date: JsDate) -> Int
|
|
69
|
+
|
|
70
|
+
/// 초 (0-59)
|
|
71
|
+
@external(javascript, "../mendix_ffi.mjs", "date_get_seconds")
|
|
72
|
+
pub fn seconds(date: JsDate) -> Int
|
|
73
|
+
|
|
74
|
+
/// 밀리초 (0-999)
|
|
75
|
+
@external(javascript, "../mendix_ffi.mjs", "date_get_milliseconds")
|
|
76
|
+
pub fn milliseconds(date: JsDate) -> Int
|
|
77
|
+
|
|
78
|
+
/// 요일 (0=일요일, 1=월요일, ..., 6=토요일)
|
|
79
|
+
@external(javascript, "../mendix_ffi.mjs", "date_get_day")
|
|
80
|
+
pub fn day_of_week(date: JsDate) -> Int
|
|
81
|
+
|
|
82
|
+
// === HTML input[type="date"] 변환 ===
|
|
83
|
+
|
|
84
|
+
import gleam/option.{type Option}
|
|
85
|
+
|
|
86
|
+
/// JsDate → "YYYY-MM-DD" 변환 (로컬 시간 기준, input[type="date"] 용)
|
|
87
|
+
@external(javascript, "../mendix_ffi.mjs", "date_to_input_value")
|
|
88
|
+
pub fn to_input_value(date: JsDate) -> String
|
|
89
|
+
|
|
90
|
+
/// "YYYY-MM-DD" → Option(JsDate) 변환 (빈 문자열 → None)
|
|
91
|
+
@external(javascript, "../mendix_ffi.mjs", "input_value_to_date")
|
|
92
|
+
pub fn from_input_value(date_string: String) -> Option(JsDate)
|
|
@@ -30,12 +30,12 @@ pub fn validation(ref: ReferenceValue) -> Option(String)
|
|
|
30
30
|
|
|
31
31
|
// === ReferenceSetValue (다중 참조) ===
|
|
32
32
|
|
|
33
|
-
/// 참조 목록 (없으면 None)
|
|
34
|
-
@external(javascript, "../mendix_ffi.mjs", "
|
|
33
|
+
/// 참조 목록 (없으면 None) — JS Array↔Gleam List 변환 포함
|
|
34
|
+
@external(javascript, "../mendix_ffi.mjs", "get_reference_set_value")
|
|
35
35
|
pub fn multi_value(rset: ReferenceSetValue) -> Option(List(a))
|
|
36
36
|
|
|
37
|
-
/// 참조 목록 설정 (None → 전체 해제)
|
|
38
|
-
@external(javascript, "../mendix_ffi.mjs", "
|
|
37
|
+
/// 참조 목록 설정 (None → 전체 해제) — Gleam List→JS Array 변환 포함
|
|
38
|
+
@external(javascript, "../mendix_ffi.mjs", "set_reference_set_value")
|
|
39
39
|
pub fn set_multi_value(rset: ReferenceSetValue, value: Option(List(a))) -> Nil
|
|
40
40
|
|
|
41
41
|
/// 읽기 전용 여부
|
|
@@ -209,6 +209,20 @@ export function modifiable_set_value(obj, option) {
|
|
|
209
209
|
obj.setValue(from_option(option));
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
// === ReferenceSetValue (Array↔List 변환) ===
|
|
213
|
+
|
|
214
|
+
export function get_reference_set_value(obj) {
|
|
215
|
+
return to_option(obj.value ? toList(obj.value) : undefined);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function set_reference_set_value(obj, option) {
|
|
219
|
+
if (option instanceof Some) {
|
|
220
|
+
obj.setValue(option[0].toArray());
|
|
221
|
+
} else {
|
|
222
|
+
obj.setValue(undefined);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
212
226
|
export function get_modifiable_read_only(obj) {
|
|
213
227
|
return obj.readOnly;
|
|
214
228
|
}
|
|
@@ -274,6 +288,149 @@ export function get_sort_asc(instr) {
|
|
|
274
288
|
return instr.asc;
|
|
275
289
|
}
|
|
276
290
|
|
|
291
|
+
// === JS Date ===
|
|
292
|
+
|
|
293
|
+
export function date_now() {
|
|
294
|
+
return new Date();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export function date_from_iso(iso_string) {
|
|
298
|
+
return new Date(iso_string);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export function date_from_timestamp(ms) {
|
|
302
|
+
return new Date(ms);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// month: Gleam 1-based → JS 0-based 변환
|
|
306
|
+
export function date_create(year, month, day, hours, minutes, seconds, ms) {
|
|
307
|
+
return new Date(year, month - 1, day, hours, minutes, seconds, ms);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export function date_to_iso(d) {
|
|
311
|
+
return d.toISOString();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function date_get_time(d) {
|
|
315
|
+
return d.getTime();
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export function date_to_string(d) {
|
|
319
|
+
return d.toString();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function date_get_full_year(d) {
|
|
323
|
+
return d.getFullYear();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// JS 0-based → Gleam 1-based 변환
|
|
327
|
+
export function date_get_month(d) {
|
|
328
|
+
return d.getMonth() + 1;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export function date_get_date(d) {
|
|
332
|
+
return d.getDate();
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function date_get_hours(d) {
|
|
336
|
+
return d.getHours();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export function date_get_minutes(d) {
|
|
340
|
+
return d.getMinutes();
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function date_get_seconds(d) {
|
|
344
|
+
return d.getSeconds();
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export function date_get_milliseconds(d) {
|
|
348
|
+
return d.getMilliseconds();
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function date_get_day(d) {
|
|
352
|
+
return d.getDay();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// === Date 변환 (JS Date ↔ HTML input[type="date"]) ===
|
|
356
|
+
|
|
357
|
+
export function date_to_input_value(jsDate) {
|
|
358
|
+
const year = jsDate.getFullYear();
|
|
359
|
+
const month = String(jsDate.getMonth() + 1).padStart(2, "0");
|
|
360
|
+
const day = String(jsDate.getDate()).padStart(2, "0");
|
|
361
|
+
return `${year}-${month}-${day}`;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export function input_value_to_date(dateString) {
|
|
365
|
+
if (!dateString) return new None();
|
|
366
|
+
const [year, month, day] = dateString.split("-").map(Number);
|
|
367
|
+
return new Some(new Date(year, month - 1, day));
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// === Big.js ===
|
|
371
|
+
|
|
372
|
+
import Big from "big.js";
|
|
373
|
+
|
|
374
|
+
export function big_from_string(s) {
|
|
375
|
+
return new Big(s);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export function big_from_int(n) {
|
|
379
|
+
return new Big(n);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export function big_from_float(f) {
|
|
383
|
+
return new Big(f);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export function big_to_string(b) {
|
|
387
|
+
return b.toString();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export function big_to_float(b) {
|
|
391
|
+
return b.toNumber();
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export function big_to_int(b) {
|
|
395
|
+
return Math.trunc(b.toNumber());
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export function big_to_fixed(b, dp) {
|
|
399
|
+
return b.toFixed(dp);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export function big_add(a, b) {
|
|
403
|
+
return a.plus(b);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export function big_sub(a, b) {
|
|
407
|
+
return a.minus(b);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export function big_mul(a, b) {
|
|
411
|
+
return a.times(b);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export function big_div(a, b) {
|
|
415
|
+
return a.div(b);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export function big_abs(b) {
|
|
419
|
+
return b.abs();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export function big_negate(b) {
|
|
423
|
+
return b.times(-1);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export function big_cmp(a, b) {
|
|
427
|
+
return a.cmp(b);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
export function big_eq(a, b) {
|
|
431
|
+
return a.eq(b);
|
|
432
|
+
}
|
|
433
|
+
|
|
277
434
|
// === Filter 빌더 (mendix/filters/builders 래핑) ===
|
|
278
435
|
// Mendix 런타임에서 제공하는 외부 모듈 (Rollup에서 external 처리)
|
|
279
436
|
import * as filters from "mendix/filters/builders";
|
|
@@ -22,6 +22,24 @@ pub fn use_effect_always(effect_fn: fn() -> Nil) -> Nil
|
|
|
22
22
|
@external(javascript, "../react_ffi.mjs", "use_effect_once")
|
|
23
23
|
pub fn use_effect_once(effect_fn: fn() -> Nil) -> Nil
|
|
24
24
|
|
|
25
|
+
// === useEffect (cleanup 반환) ===
|
|
26
|
+
// Gleam fn() -> fn() -> Nil = JS에서 함수를 반환하는 함수 → React cleanup으로 인식
|
|
27
|
+
|
|
28
|
+
/// 의존성 배열과 함께 실행 (cleanup 함수 반환)
|
|
29
|
+
@external(javascript, "../react_ffi.mjs", "use_effect")
|
|
30
|
+
pub fn use_effect_cleanup(
|
|
31
|
+
setup: fn() -> fn() -> Nil,
|
|
32
|
+
deps: List(a),
|
|
33
|
+
) -> Nil
|
|
34
|
+
|
|
35
|
+
/// 매 렌더링마다 실행 + cleanup
|
|
36
|
+
@external(javascript, "../react_ffi.mjs", "use_effect_always")
|
|
37
|
+
pub fn use_effect_always_cleanup(setup: fn() -> fn() -> Nil) -> Nil
|
|
38
|
+
|
|
39
|
+
/// 마운트 시 한 번만 실행 + cleanup
|
|
40
|
+
@external(javascript, "../react_ffi.mjs", "use_effect_once")
|
|
41
|
+
pub fn use_effect_once_cleanup(setup: fn() -> fn() -> Nil) -> Nil
|
|
42
|
+
|
|
25
43
|
// === useMemo / useCallback ===
|
|
26
44
|
|
|
27
45
|
/// 메모이제이션된 값 계산
|