@freereportjs/vue 0.0.0-stage → 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,86 @@
1
+ FreeReport License
2
+ Version 1.0, 2026-10-15
3
+
4
+ Copyright (c) 2026 2nd Korea (세컨드코리아). All rights reserved.
5
+ Contact: help@2nd-korea.com · https://freereport.app/pricing/
6
+
7
+ This license covers the FreeReport software, including the packages @freereportjs/core,
8
+ @freereportjs/react, @freereportjs/vue, @freereportjs/svelte and @freereportjs/angular, the
9
+ FreeReport Windows programs, their source code and the files built from them (the "Software").
10
+
11
+ 1. Personal use is free
12
+
13
+ An individual may use, copy and modify the Software free of charge for personal,
14
+ educational, research or other non-commercial purposes, including personal websites,
15
+ open-source projects that are not run by a company, and learning or evaluation.
16
+
17
+ 2. Company use needs a domain license
18
+
19
+ Any use by or for a company, organization, public body or other business ("Company"),
20
+ whether the product is sold, used internally or offered to customers, requires a paid
21
+ Company License. A Company may evaluate the Software for up to 30 days without a license.
22
+
23
+ - A Company License is issued for one domain (for example example.com) and covers that
24
+ domain and its www host (www.example.com). Each other subdomain (for example
25
+ erp.example.com) needs its own Company License, unless the license is issued for
26
+ *.example.com. Applications without a domain (intranets reached by address, desktop
27
+ applications) count as one domain per installation site.
28
+ - Annual license: KRW 500,000 per domain per year. Valid for one year from the date it is
29
+ issued; renewable. All updates released during the term are included.
30
+ - Perpetual license: KRW 900,000 per domain, paid once. It does not expire. Versions
31
+ released within one year of the issue date are covered; later versions need a renewal
32
+ of updates.
33
+ - With the FreeReport Windows programs (such as the local print agent) the fees are doubled:
34
+ KRW 1,000,000 per domain per year, or KRW 1,800,000 perpetual.
35
+ - Fees exclude VAT. There is no limit on developers, end users or output volume.
36
+ - A license key is provided with each Company License. Setting the key removes the
37
+ console notice described in section 5.
38
+
39
+ 3. Conditions for all users
40
+
41
+ - Keep this license and the copyright notice in copies of the Software.
42
+ - Do not sell, rent or sublicense the Software itself, or offer it as a standalone
43
+ reporting component or library, with or without changes.
44
+ - Do not remove or work around the license check, or share license keys outside the
45
+ licensed domain.
46
+
47
+ 4. No warranty
48
+
49
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
50
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
51
+ PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
52
+ FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ARISING FROM THE SOFTWARE OR ITS USE.
53
+
54
+ 5. Usage report
55
+
56
+ When the Software runs on a public domain (not localhost or a private network address),
57
+ it sends the domain name, the page address without query string, the Software version
58
+ and whether a license key is set to freereport.app once a day. No report data and no
59
+ information about end users is sent. Without a license key on such a domain it also
60
+ prints a notice in the browser developer console.
61
+
62
+ ---------------------------------------------------------------------------------------
63
+
64
+ FreeReport 라이선스 (요약, 한국어)
65
+
66
+ - 개인: 개인적·교육·연구 등 비상업적 용도로 무료로 사용, 복제, 수정할 수 있습니다.
67
+ - 회사: 회사, 단체, 공공기관 등 업무용으로 쓰려면 판매용·내부용·고객 제공용 모두 유료
68
+ 회사 라이선스가 필요합니다. 30일 동안은 평가 목적으로 라이선스 없이 써 볼 수 있습니다.
69
+ - 도메인 1개(www 포함) 또는 사내망 설치처 1곳 기준입니다. 다른 서브도메인은 별도
70
+ 라이선스가 필요하며, *.example.com으로 발급하면 모든 서브도메인에 적용됩니다.
71
+ - 연간: 도메인당 연 500,000원. 발급일로부터 1년간 유효하며 기간 중 업데이트를 포함합니다.
72
+ - 영구: 도메인당 900,000원(1회). 기간 제한 없이 쓸 수 있고, 발급 후 1년 안에 나온
73
+ 버전까지 포함합니다.
74
+ - Windows 프로그램(로컬 인쇄 에이전트 등)을 함께 쓰면 2배입니다: 연 1,000,000원 또는
75
+ 영구 1,800,000원.
76
+ - 부가세 별도이며, 개발자·사용자·출력 건수 제한은 없습니다.
77
+ - 라이선스마다 키를 발급하며, 키를 설정하면 콘솔 안내가 사라집니다.
78
+ - 모든 사용자: 저작권과 이 라이선스 문구를 유지해야 하며, 소프트웨어 자체를 판매하거나
79
+ 별도 리포팅 라이브러리로 재배포할 수 없고, 라이선스 확인을 제거하거나 키를 다른
80
+ 도메인에 공유할 수 없습니다.
81
+ - 보증 없음: 소프트웨어는 있는 그대로 제공됩니다.
82
+ - 사용 보고: 공개 도메인에서 실행되면 하루 한 번 도메인 이름, 쿼리 문자열을 뺀 페이지
83
+ 주소, 버전, 라이선스 키 설정 여부를 freereport.app으로 보냅니다. 보고서 데이터나 최종
84
+ 사용자 정보는 보내지 않습니다.
85
+
86
+ 문의: help@2nd-korea.com · 대표번호 070-7768-1326
package/README.md CHANGED
@@ -1,3 +1,35 @@
1
- # Temporary Holding Version
1
+ # @freereportjs/vue
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Vue 3 components for [FreeReport](https://freereport.app): the report viewer and the banded report designer.
4
+
5
+ ```bash
6
+ npm i @freereportjs/core @freereportjs/vue
7
+ ```
8
+
9
+ ```vue
10
+ <script setup>
11
+ import { FreeReportDesigner, FreeReportViewer } from '@freereportjs/vue';
12
+ import '@freereportjs/core/styles.css';
13
+ </script>
14
+
15
+ <template>
16
+ <FreeReportViewer ref="viewer" :definition="def" :data="{ rows }" lang="en" :height="720" />
17
+ <FreeReportDesigner v-model:definition="def" :data="{ rows }" @save="save" />
18
+ </template>
19
+ ```
20
+
21
+ The viewer exposes `viewer` and `report`, the designer `designer`. The designer emits `change` / `update:definition`
22
+ after edits and `save`. Both default to `height: 100%` with a 480px minimum (`height` / `min-height` props).
23
+ Docs: https://freereport.app/docs/
24
+
25
+ ## License
26
+
27
+ Free for personal use. Company use needs a domain license: KRW 500,000 per domain per year, or KRW 900,000 once (perpetual)
28
+ (VAT separate). See https://freereport.app/pricing/ and the LICENSE file.
29
+
30
+ 개인은 무료, 회사는 도메인당 연 50만 원 또는 영구 90만 원(부가세 별도)입니다. 자세한 내용은 https://freereport.app/pricing/
31
+
32
+ ```js
33
+ import { setLicenseKey } from '@freereportjs/core';
34
+ setLicenseKey('FR1....'); // or the licenseKey prop
35
+ ```
@@ -0,0 +1,122 @@
1
+ import * as vue from 'vue';
2
+ import { PropType } from 'vue';
3
+ import { ReportDefinition, ReportData, DesignerOptions, ViewerOptions } from '@freereportjs/core';
4
+ export { Designer, DesignerOptions, LayoutResult, OutputEvent, Report, ReportData, ReportDefinition, ReportOptions, Viewer, ViewerOptions, createReport, layoutReport } from '@freereportjs/core';
5
+
6
+ /**
7
+ * `<FreeReportViewer :definition="def" :data="data" />`: toolbar, parameter panel and paged report.
8
+ * `definition`, `data`, `params` and `zoom` update the viewer in place; other props recreate it.
9
+ * Exposes `viewer` and `report` (template ref).
10
+ */
11
+ declare const FreeReportViewer: vue.DefineComponent<vue.ExtractPropTypes<{
12
+ definition: {
13
+ type: PropType<ReportDefinition>;
14
+ required: true;
15
+ };
16
+ data: PropType<ReportData>;
17
+ /** Parameter values (merged over the definition's defaults). */
18
+ params: PropType<Record<string, unknown>>;
19
+ lang: PropType<ViewerOptions["lang"]>;
20
+ zoom: PropType<ViewerOptions["zoom"]>;
21
+ toolbar: PropType<ViewerOptions["toolbar"]>;
22
+ licenseKey: StringConstructor;
23
+ /** Called before every print/export; return false to cancel it. */
24
+ onOutput: PropType<ViewerOptions["onOutput"]>;
25
+ pdfSecurity: PropType<ViewerOptions["pdfSecurity"]>;
26
+ fileName: StringConstructor;
27
+ fetchData: PropType<ViewerOptions["fetchData"]>;
28
+ /** Host height; number = px. */
29
+ height: {
30
+ type: (StringConstructor | NumberConstructor)[];
31
+ default: string;
32
+ };
33
+ minHeight: {
34
+ type: (StringConstructor | NumberConstructor)[];
35
+ default: number;
36
+ };
37
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
38
+ [key: string]: any;
39
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
40
+ definition: {
41
+ type: PropType<ReportDefinition>;
42
+ required: true;
43
+ };
44
+ data: PropType<ReportData>;
45
+ /** Parameter values (merged over the definition's defaults). */
46
+ params: PropType<Record<string, unknown>>;
47
+ lang: PropType<ViewerOptions["lang"]>;
48
+ zoom: PropType<ViewerOptions["zoom"]>;
49
+ toolbar: PropType<ViewerOptions["toolbar"]>;
50
+ licenseKey: StringConstructor;
51
+ /** Called before every print/export; return false to cancel it. */
52
+ onOutput: PropType<ViewerOptions["onOutput"]>;
53
+ pdfSecurity: PropType<ViewerOptions["pdfSecurity"]>;
54
+ fileName: StringConstructor;
55
+ fetchData: PropType<ViewerOptions["fetchData"]>;
56
+ /** Host height; number = px. */
57
+ height: {
58
+ type: (StringConstructor | NumberConstructor)[];
59
+ default: string;
60
+ };
61
+ minHeight: {
62
+ type: (StringConstructor | NumberConstructor)[];
63
+ default: number;
64
+ };
65
+ }>> & Readonly<{}>, {
66
+ height: string | number;
67
+ minHeight: string | number;
68
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
69
+ /**
70
+ * `<FreeReportDesigner v-model:definition="def" />`: the banded report designer.
71
+ * Emits `change` (and `update:definition`) after edits, debounced; `save` when the user presses Save
72
+ * (without a listener Save downloads the JSON). A new `definition` replaces the document, except the one it just emitted.
73
+ * Exposes `designer` (template ref).
74
+ */
75
+ declare const FreeReportDesigner: vue.DefineComponent<vue.ExtractPropTypes<{
76
+ definition: PropType<ReportDefinition>;
77
+ /** Sample data for the field list and the preview. */
78
+ data: PropType<ReportData>;
79
+ lang: PropType<DesignerOptions["lang"]>;
80
+ zoom: NumberConstructor;
81
+ licenseKey: StringConstructor;
82
+ /** Host height; number = px. */
83
+ height: {
84
+ type: (StringConstructor | NumberConstructor)[];
85
+ default: string;
86
+ };
87
+ minHeight: {
88
+ type: (StringConstructor | NumberConstructor)[];
89
+ default: number;
90
+ };
91
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
92
+ [key: string]: any;
93
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
94
+ change: (_def: ReportDefinition) => true;
95
+ 'update:definition': (_def: ReportDefinition) => true;
96
+ save: (_def: ReportDefinition) => true;
97
+ }, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
98
+ definition: PropType<ReportDefinition>;
99
+ /** Sample data for the field list and the preview. */
100
+ data: PropType<ReportData>;
101
+ lang: PropType<DesignerOptions["lang"]>;
102
+ zoom: NumberConstructor;
103
+ licenseKey: StringConstructor;
104
+ /** Host height; number = px. */
105
+ height: {
106
+ type: (StringConstructor | NumberConstructor)[];
107
+ default: string;
108
+ };
109
+ minHeight: {
110
+ type: (StringConstructor | NumberConstructor)[];
111
+ default: number;
112
+ };
113
+ }>> & Readonly<{
114
+ onChange?: ((_def: ReportDefinition) => any) | undefined;
115
+ "onUpdate:definition"?: ((_def: ReportDefinition) => any) | undefined;
116
+ onSave?: ((_def: ReportDefinition) => any) | undefined;
117
+ }>, {
118
+ height: string | number;
119
+ minHeight: string | number;
120
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
121
+
122
+ export { FreeReportDesigner, FreeReportViewer };
package/dist/index.js ADDED
@@ -0,0 +1,144 @@
1
+ // src/index.ts
2
+ import {
3
+ createDesigner,
4
+ createViewer
5
+ } from "@freereportjs/core";
6
+ import { defineComponent, getCurrentInstance, h, onBeforeUnmount, onMounted, ref, toRaw, watch } from "vue";
7
+ import { createReport, layoutReport } from "@freereportjs/core";
8
+ var css = (v) => typeof v === "number" ? `${v}px` : v;
9
+ var frame = (height, minHeight, inner) => h("div", { style: { position: "relative", height: css(height), minHeight: css(minHeight) } }, [
10
+ h("div", { ref: inner, style: { position: "absolute", inset: "0" } })
11
+ ]);
12
+ var FreeReportViewer = defineComponent({
13
+ name: "FreeReportViewer",
14
+ props: {
15
+ definition: { type: Object, required: true },
16
+ data: [Object, Array],
17
+ /** Parameter values (merged over the definition's defaults). */
18
+ params: Object,
19
+ lang: String,
20
+ zoom: [Number, String],
21
+ toolbar: Object,
22
+ licenseKey: String,
23
+ /** Called before every print/export; return false to cancel it. */
24
+ onOutput: Function,
25
+ pdfSecurity: Object,
26
+ fileName: String,
27
+ fetchData: Function,
28
+ /** Host height; number = px. */
29
+ height: { type: [Number, String], default: "100%" },
30
+ minHeight: { type: [Number, String], default: 480 }
31
+ },
32
+ setup(props, { expose }) {
33
+ const host = ref(null);
34
+ let viewer = null;
35
+ const create = () => {
36
+ viewer?.destroy();
37
+ viewer = createViewer(host.value, {
38
+ definition: props.definition,
39
+ data: props.data,
40
+ params: props.params,
41
+ lang: props.lang,
42
+ zoom: props.zoom,
43
+ toolbar: props.toolbar,
44
+ licenseKey: props.licenseKey,
45
+ pdfSecurity: props.pdfSecurity,
46
+ fileName: props.fileName,
47
+ onOutput: (e) => props.onOutput?.(e),
48
+ fetchData: props.fetchData && ((params) => props.fetchData(params))
49
+ });
50
+ };
51
+ onMounted(create);
52
+ onBeforeUnmount(() => {
53
+ viewer?.destroy();
54
+ viewer = null;
55
+ });
56
+ watch(() => [props.definition, props.data], ([def, data], [oldDef, oldData]) => {
57
+ if (!viewer) return;
58
+ if (def !== oldDef) viewer.report.setDefinition(def);
59
+ if (data !== oldData) viewer.report.setData(data ?? {});
60
+ void viewer.refresh();
61
+ });
62
+ watch(() => props.params, (p) => void viewer?.setParams(p ?? {}));
63
+ watch(() => props.zoom, (z) => viewer?.setZoom(z ?? "width"));
64
+ watch(
65
+ () => JSON.stringify([props.lang, props.toolbar, props.licenseKey, props.pdfSecurity, props.fileName, !!props.fetchData]),
66
+ () => {
67
+ if (viewer) create();
68
+ }
69
+ );
70
+ expose({
71
+ get viewer() {
72
+ return viewer;
73
+ },
74
+ get report() {
75
+ return viewer?.report ?? null;
76
+ }
77
+ });
78
+ return () => frame(props.height, props.minHeight, host);
79
+ }
80
+ });
81
+ var FreeReportDesigner = defineComponent({
82
+ name: "FreeReportDesigner",
83
+ props: {
84
+ definition: Object,
85
+ /** Sample data for the field list and the preview. */
86
+ data: [Object, Array],
87
+ lang: String,
88
+ zoom: Number,
89
+ licenseKey: String,
90
+ /** Host height; number = px. */
91
+ height: { type: [Number, String], default: "100%" },
92
+ minHeight: { type: [Number, String], default: 480 }
93
+ },
94
+ emits: {
95
+ change: (_def) => true,
96
+ "update:definition": (_def) => true,
97
+ save: (_def) => true
98
+ },
99
+ setup(props, { emit, expose }) {
100
+ const host = ref(null);
101
+ const hasSave = !!getCurrentInstance()?.vnode.props?.onSave;
102
+ let designer = null;
103
+ let emitted = null;
104
+ const create = () => {
105
+ const current = designer?.getDefinition();
106
+ designer?.destroy();
107
+ designer = createDesigner(host.value, {
108
+ definition: current ?? (props.definition && toRaw(props.definition)),
109
+ data: props.data,
110
+ lang: props.lang,
111
+ zoom: props.zoom,
112
+ licenseKey: props.licenseKey,
113
+ onChange: (def) => {
114
+ emitted = def;
115
+ emit("change", def);
116
+ emit("update:definition", def);
117
+ },
118
+ onSave: hasSave ? (def) => emit("save", def) : void 0
119
+ });
120
+ };
121
+ onMounted(create);
122
+ onBeforeUnmount(() => {
123
+ designer?.destroy();
124
+ designer = null;
125
+ });
126
+ watch(() => props.definition, (def) => {
127
+ if (def && toRaw(def) !== emitted) designer?.setDefinition(toRaw(def));
128
+ });
129
+ watch(() => props.data, (d) => designer?.setData(d ?? {}));
130
+ watch(() => [props.lang, props.licenseKey], () => {
131
+ if (designer) create();
132
+ });
133
+ expose({ get designer() {
134
+ return designer;
135
+ } });
136
+ return () => frame(props.height, props.minHeight, host);
137
+ }
138
+ });
139
+ export {
140
+ FreeReportDesigner,
141
+ FreeReportViewer,
142
+ createReport,
143
+ layoutReport
144
+ };
package/package.json CHANGED
@@ -1,6 +1,51 @@
1
1
  {
2
2
  "name": "@freereportjs/vue",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Vue 3 components for FreeReport, the web reporting engine: report viewer and banded report designer (free for personal use).",
5
+ "license": "SEE LICENSE IN LICENSE",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "peerDependencies": {
21
+ "@freereportjs/core": "^0.1.0",
22
+ "vue": ">=3.3"
23
+ },
24
+ "devDependencies": {
25
+ "@freereportjs/core": "^0.1.0",
26
+ "@vue/test-utils": "^2.5.1",
27
+ "jsdom": "^30.1.2",
28
+ "tsup": "^8.5.1",
29
+ "typescript": "~5.9.3",
30
+ "vitest": "^5.0.4",
31
+ "vue": ">=3.3"
32
+ },
33
+ "keywords": [
34
+ "report",
35
+ "reporting",
36
+ "report-designer",
37
+ "vue",
38
+ "pdf",
39
+ "@freereportjs/core"
40
+ ],
41
+ "homepage": "https://freereport.app",
42
+ "author": "secondkorea",
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "scripts": {
47
+ "build": "tsup",
48
+ "test": "vitest run",
49
+ "typecheck": "tsc -p tsconfig.json"
50
+ }
6
51
  }