@operato/scene-table 7.3.5 → 7.3.18

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/schema.graphql CHANGED
@@ -201,6 +201,7 @@ type Attachment {
201
201
  refBy: String
202
202
  refType: String
203
203
  size: String!
204
+ tags: Object
204
205
  updatedAt: DateTimeISO!
205
206
  updater: User
206
207
  }
@@ -219,6 +220,7 @@ input AttachmentPatch {
219
220
  name: String
220
221
  refBy: String
221
222
  refType: String
223
+ tags: Object
222
224
  }
223
225
 
224
226
  """Entity for AttributeSet"""
@@ -747,9 +749,11 @@ scalar EmailAddress @specifiedBy(url: "https://html.spec.whatwg.org/multipage/in
747
749
  """Entity for Employee"""
748
750
  type Employee {
749
751
  active: Boolean
750
- address: String!
752
+ address: String
751
753
  alias: String
752
754
  approvalLines: [ApprovalLine!]!
755
+ bankAccount: String
756
+ bankName: String
753
757
  contact: Contact
754
758
  controlNo: String!
755
759
  createdAt: DateTimeISO
@@ -758,8 +762,10 @@ type Employee {
758
762
  department: Department
759
763
  domain: Domain!
760
764
  email: EmailAddress
765
+ emergencyContact: String
766
+ emergencyContactPhone: String
761
767
  extension: String
762
- hiredOn: String
768
+ hiredOn: DateTimeISO
763
769
  id: ID!
764
770
  jobPosition: String
765
771
  jobResponsibility: String
@@ -769,7 +775,7 @@ type Employee {
769
775
  phone: String
770
776
  photo: String
771
777
  profile: Profile
772
- retiredAt: String
778
+ retiredOn: DateTimeISO
773
779
  supervises: [Employee!]!
774
780
  supervisor: Employee
775
781
  type: String
@@ -787,18 +793,22 @@ type EmployeeList {
787
793
  input EmployeePatch {
788
794
  active: Boolean
789
795
  alias: String
796
+ bankAccount: String
797
+ bankName: String
790
798
  contact: ObjectRefForContact
791
799
  controlNo: String
792
800
  cuFlag: String
793
801
  department: ObjectRefForDepartment
794
- hiredOn: String
802
+ emergencyContact: String
803
+ emergencyContactPhone: String
804
+ hiredOn: DateTimeISO
795
805
  id: ID
796
806
  jobPosition: String
797
807
  jobResponsibility: String
798
808
  name: String
799
809
  note: String
800
810
  photo: Upload
801
- retiredAt: String
811
+ retiredOn: DateTimeISO
802
812
  supervisor: ObjectRefForEmployee
803
813
  type: EmployeeType
804
814
  user: ObjectRefForUser
@@ -1163,7 +1173,6 @@ type Menu {
1163
1173
  name: String
1164
1174
  pagination: Boolean
1165
1175
  parent: Menu
1166
- privilege: PrivilegeObject
1167
1176
  rank: Float
1168
1177
  resourceId: String
1169
1178
  resourceName: String
@@ -1485,7 +1494,6 @@ input MenuPatch {
1485
1494
  name: String
1486
1495
  pagination: Boolean
1487
1496
  parent: ObjectRef
1488
- privilege: PrivilegeInput
1489
1497
  rank: Int
1490
1498
  resourceId: String
1491
1499
  resourceName: String
@@ -1503,7 +1511,9 @@ type Mutation {
1503
1511
  """To activate user"""
1504
1512
  activateUser(userId: String!): Boolean!
1505
1513
 
1506
- """To attach a contact on Employee"""
1514
+ """
1515
+ Attaches an existing contact to an employee. The contact is identified by its ID and the employee is identified by their ID.
1516
+ """
1507
1517
  attachContact(contactId: String!, id: String!): Employee!
1508
1518
  cancelInvitation(email: EmailAddress!, reference: String!, type: String!): Boolean!
1509
1519
 
@@ -1560,7 +1570,9 @@ type Mutation {
1560
1570
  """To create domain (Only superuser is granted this privilege.)"""
1561
1571
  createDomain(domainInput: DomainPatch!): Domain!
1562
1572
 
1563
- """To create new Employee"""
1573
+ """
1574
+ Creates a new employee record with the provided details. Optionally associates the employee with a supervisor, department, and system user. If a photo is provided, it will be attached to the employee record.
1575
+ """
1564
1576
  createEmployee(employee: NewEmployee!): Employee!
1565
1577
 
1566
1578
  """To create new Entity"""
@@ -1723,10 +1735,14 @@ type Mutation {
1723
1735
  """To delete multiple domains (Only superuser is granted this privilege.)"""
1724
1736
  deleteDomains(names: [String!]!): Boolean!
1725
1737
 
1726
- """To delete Employee"""
1738
+ """
1739
+ Deletes an employee record identified by the given ID. Also deletes any attachments associated with the employee.
1740
+ """
1727
1741
  deleteEmployee(id: String!): Boolean!
1728
1742
 
1729
- """To delete multiple Employees"""
1743
+ """
1744
+ Deletes multiple employee records identified by the given IDs. Also deletes any attachments associated with each employee.
1745
+ """
1730
1746
  deleteEmployees(ids: [String!]!): Boolean!
1731
1747
 
1732
1748
  """To delete multiple Entities"""
@@ -1906,7 +1922,9 @@ type Mutation {
1906
1922
  """To delete some users"""
1907
1923
  deleteUsers(emails: [String!]!): Boolean!
1908
1924
 
1909
- """To detach a contact from Employee"""
1925
+ """
1926
+ Detaches an existing contact from an employee. The employee is identified by their ID.
1927
+ """
1910
1928
  detachContact(id: String!): Employee!
1911
1929
 
1912
1930
  """To disconnect a connection"""
@@ -1948,7 +1966,9 @@ type Mutation {
1948
1966
  """To import multiple Departments"""
1949
1967
  importDepartments(departments: [DepartmentPatch!]!): Boolean!
1950
1968
 
1951
- """To import multiple Employees"""
1969
+ """
1970
+ Imports multiple employee records into the system. Each employee record must be provided in the EmployeePatch format.
1971
+ """
1952
1972
  importEmployees(employees: [EmployeePatch!]!): Boolean!
1953
1973
 
1954
1974
  """To import multiple MenuButtons"""
@@ -2028,11 +2048,14 @@ type Mutation {
2028
2048
  visibility: String!
2029
2049
  ): BoardTemplate!
2030
2050
 
2031
- """To register employee as a system user"""
2051
+ """
2052
+ Registers an existing employee as a system user, granting them access to the system. The employee is identified by their ID.
2053
+ """
2032
2054
  registerEmployeeAsSystemUser(
2033
2055
  """Employee Id"""
2034
- id: String!
2056
+ employeeId: String!
2035
2057
  ): Boolean!
2058
+ registerSchedule(schedule: NewSchedule!): ID!
2036
2059
 
2037
2060
  """To release a Board"""
2038
2061
  releaseBoard(id: String!): Board!
@@ -2083,6 +2106,7 @@ type Mutation {
2083
2106
 
2084
2107
  """To transfer owner of domain"""
2085
2108
  transferOwner(email: EmailAddress!): Boolean!
2109
+ unregisterSchedule(handle: ID!): Boolean!
2086
2110
  updateAppliance(id: String!, patch: AppliancePatch!): Appliance!
2087
2111
  updateApplication(id: String!, patch: ApplicationPatch!): Application!
2088
2112
 
@@ -2123,7 +2147,9 @@ type Mutation {
2123
2147
  """To update multiple domains (Only superuser is granted this privilege.)"""
2124
2148
  updateDomains(patches: [DomainPatch!]!): Boolean!
2125
2149
 
2126
- """To modify Employee information"""
2150
+ """
2151
+ Updates the details of an existing employee identified by the given ID. Optionally updates the supervisor, department, system user, and photo associated with the employee.
2152
+ """
2127
2153
  updateEmployee(id: String!, patch: EmployeePatch!): Employee!
2128
2154
 
2129
2155
  """To modify Entity' information"""
@@ -2178,7 +2204,9 @@ type Mutation {
2178
2204
  """To modify multiple Departments' information"""
2179
2205
  updateMultipleDepartment(patches: [DepartmentPatch!]!): [Department!]!
2180
2206
 
2181
- """To modify multiple Employees' information"""
2207
+ """
2208
+ Updates or creates multiple employee records based on the provided patches. New employees are created if the "cuFlag" is "+", and existing employees are updated if the "cuFlag" is "M".
2209
+ """
2182
2210
  updateMultipleEmployee(patches: [EmployeePatch!]!): [Employee!]!
2183
2211
 
2184
2212
  """To modify multiple Entitys' information"""
@@ -2282,6 +2310,7 @@ type Mutation {
2282
2310
 
2283
2311
  """To modify scenario information"""
2284
2312
  updateScenario(name: String!, patch: ScenarioPatch!): Scenario!
2313
+ updateSchedule(schedule: SchedulePatch!): ID!
2285
2314
 
2286
2315
  """To update secure IP list for domain"""
2287
2316
  updateSecureIPList(iplist: Object!): Object
@@ -2345,6 +2374,7 @@ input NewAttachment {
2345
2374
  file: Upload!
2346
2375
  refBy: String
2347
2376
  refType: String
2377
+ tags: Object
2348
2378
  }
2349
2379
 
2350
2380
  input NewAttributeSet {
@@ -2429,17 +2459,21 @@ input NewDepartment {
2429
2459
  input NewEmployee {
2430
2460
  active: Boolean
2431
2461
  alias: String
2462
+ bankAccount: String
2463
+ bankName: String
2432
2464
  contact: ObjectRefForContact
2433
2465
  controlNo: String!
2434
2466
  department: ObjectRefForDepartment
2467
+ emergencyContact: String
2468
+ emergencyContactPhone: String
2435
2469
  extension: String
2436
- hiredOn: String
2470
+ hiredOn: DateTimeISO
2437
2471
  jobPosition: String
2438
2472
  jobResponsibility: String
2439
2473
  name: String!
2440
2474
  note: String
2441
2475
  photo: Upload
2442
- retiredAt: String
2476
+ retiredOn: DateTimeISO
2443
2477
  supervisor: ObjectRefForEmployee
2444
2478
  type: EmployeeType
2445
2479
  user: ObjectRefForUser
@@ -2539,7 +2573,6 @@ input NewMenu {
2539
2573
  name: String!
2540
2574
  pagination: Boolean
2541
2575
  parent: ObjectRef
2542
- privilege: PrivilegeInput
2543
2576
  rank: Int
2544
2577
  resourceId: String
2545
2578
  resourceName: String
@@ -2782,13 +2815,22 @@ input NewScenario {
2782
2815
  active: Boolean
2783
2816
  description: String
2784
2817
  name: String!
2785
- privilege: PrivilegeInput
2818
+ role: ObjectRef
2786
2819
  schedule: String
2787
2820
  timezone: String
2788
2821
  ttl: Float
2789
2822
  type: String
2790
2823
  }
2791
2824
 
2825
+ input NewSchedule {
2826
+ client: ScheduleClientInput!
2827
+ name: String!
2828
+ schedule: String
2829
+ task: ScheduleTaskInput!
2830
+ timezone: String
2831
+ type: String!
2832
+ }
2833
+
2792
2834
  input NewSetting {
2793
2835
  category: String!
2794
2836
  description: String
@@ -3070,7 +3112,7 @@ input ObjectRefForEmployee {
3070
3112
  """Field description"""
3071
3113
  description: String
3072
3114
  email: EmailAddress
3073
- hiredOn: String
3115
+ hiredOn: DateTimeISO
3074
3116
 
3075
3117
  """Field id"""
3076
3118
  id: ID!
@@ -3274,6 +3316,18 @@ input PartnerSettingPatch {
3274
3316
  value: String
3275
3317
  }
3276
3318
 
3319
+ type PasswordRule {
3320
+ allowRepeat: Boolean
3321
+ digit: Boolean
3322
+ looseCharacterLength: Float
3323
+ lowerCase: Boolean
3324
+ specialCharacter: Boolean
3325
+ tightCharacterLength: Float
3326
+ upperCase: Boolean
3327
+ useLoosePattern: Boolean
3328
+ useTightPattern: Boolean
3329
+ }
3330
+
3277
3331
  """Entity for PayloadLog"""
3278
3332
  type PayloadLog {
3279
3333
  createdAt: DateTimeISO
@@ -3395,13 +3449,6 @@ type Privilege {
3395
3449
  updater: User
3396
3450
  }
3397
3451
 
3398
- input PrivilegeInput {
3399
- category: String
3400
- owner: Boolean
3401
- privilege: String
3402
- super: Boolean
3403
- }
3404
-
3405
3452
  type PrivilegeList {
3406
3453
  items: [Privilege!]
3407
3454
  total: Int
@@ -3528,19 +3575,25 @@ type Query {
3528
3575
  boardsCreatedByMe(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): BoardList!
3529
3576
  chatCompletion(input: ChatCompletionInput!): ChatCompletionOutput!
3530
3577
 
3531
- """To check if system would provide default password to create new user"""
3578
+ """
3579
+ Checks if the system is configured to provide a default password for new users.
3580
+ """
3532
3581
  checkDefaultPassword: Boolean!
3533
3582
 
3534
- """To check if system would provide default password to create new user"""
3583
+ """
3584
+ Determines whether the system provides a default password when creating a new user.
3585
+ """
3535
3586
  checkResettablePasswordToDefault: Boolean!
3536
3587
 
3537
3588
  """To fetch the preset of role for new user"""
3538
3589
  checkRolePreset: [Role!]!
3539
3590
 
3540
- """To check if current user is belongs to current domain"""
3591
+ """
3592
+ Checks if the current authenticated user belongs to the current domain.
3593
+ """
3541
3594
  checkUserBelongsDomain: Boolean!
3542
3595
 
3543
- """..."""
3596
+ """Checks if a user with the given email address exists in the system."""
3544
3597
  checkUserExistence(email: EmailAddress!): Boolean!
3545
3598
 
3546
3599
  """To fetch common approval lines"""
@@ -3600,10 +3653,14 @@ type Query {
3600
3653
  """To fetch multiple appliance"""
3601
3654
  edges(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): ApplianceList!
3602
3655
 
3603
- """To fetch a Employee"""
3656
+ """
3657
+ Fetches a specific employee by their unique ID. Returns the employee object if found, or null if not found.
3658
+ """
3604
3659
  employee(id: String!): Employee
3605
3660
 
3606
- """To fetch multiple Employees"""
3661
+ """
3662
+ Fetches a list of employees based on provided query parameters. Supports searching by name, control number, and alias.
3663
+ """
3607
3664
  employees(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): EmployeeList!
3608
3665
 
3609
3666
  """To fetch multiple Entities"""
@@ -3761,6 +3818,11 @@ type Query {
3761
3818
  partnerSettings(filters: [Filter!]!, pagination: Pagination!, partnerDomain: ObjectRef!, sortings: [Sorting!]!): PartnerSettingList!
3762
3819
  partners(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): PartnerList!
3763
3820
 
3821
+ """
3822
+ Retrieves the current password rule configuration for the system, such as required character types and minimum length.
3823
+ """
3824
+ passwordRule: PasswordRule!
3825
+
3764
3826
  """To fetch a PayloadLog"""
3765
3827
  payloadLog(id: String!): PayloadLog!
3766
3828
 
@@ -3817,6 +3879,10 @@ type Query {
3817
3879
 
3818
3880
  """To fetch multiple scenarios"""
3819
3881
  scenarios(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): ScenarioList!
3882
+ schedule(id: ID!): Schedule
3883
+
3884
+ """To fetch multiple Schedules"""
3885
+ schedules(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): ScheduleList!
3820
3886
  searchCustomers(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): DomainList!
3821
3887
 
3822
3888
  """To fetch domain"""
@@ -3864,7 +3930,7 @@ type Query {
3864
3930
  """To fetch multiple Themes"""
3865
3931
  themes(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): ThemeList!
3866
3932
 
3867
- """To fetch user"""
3933
+ """Fetches a user by their email address within the current domain."""
3868
3934
  user(email: EmailAddress!): User!
3869
3935
 
3870
3936
  """To fetch Menus by role"""
@@ -3873,7 +3939,9 @@ type Query {
3873
3939
  """To fetch roles of a user"""
3874
3940
  userRoles(userId: String!): [UserRole!]!
3875
3941
 
3876
- """To fetch multiple users"""
3942
+ """
3943
+ Fetches a list of users based on provided search parameters within the current domain.
3944
+ """
3877
3945
  users(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): UserList!
3878
3946
  vendors: [Domain!]!
3879
3947
  }
@@ -3935,6 +4003,7 @@ type Scenario {
3935
4003
  """accessible and executable system-wide"""
3936
4004
  public: Boolean
3937
4005
  publishTags: [Connection!]!
4006
+ role: Role
3938
4007
  schedule: String
3939
4008
  scheduleId: String
3940
4009
  state: String
@@ -4016,7 +4085,7 @@ input ScenarioPatch {
4016
4085
  description: String
4017
4086
  id: ID
4018
4087
  name: String
4019
- privilege: PrivilegeInput
4088
+ role: ObjectRef
4020
4089
  schedule: String
4021
4090
  steps: [StepPatch!]
4022
4091
  timezone: String
@@ -4029,6 +4098,81 @@ type ScenarioQueueState {
4029
4098
  queue: [PendingObject!]!
4030
4099
  }
4031
4100
 
4101
+ type Schedule {
4102
+ client: ScheduleClient!
4103
+ id: ID!
4104
+ name: String
4105
+ schedule: String
4106
+ task: ScheduleTask!
4107
+ timezone: String
4108
+ type: String!
4109
+ }
4110
+
4111
+ type ScheduleClient {
4112
+ application: String!
4113
+ group: String!
4114
+ key: String!
4115
+ operation: String!
4116
+ type: String!
4117
+ }
4118
+
4119
+ input ScheduleClientInput {
4120
+ application: String!
4121
+ group: String!
4122
+ key: String!
4123
+ operation: String!
4124
+ type: String!
4125
+ }
4126
+
4127
+ type ScheduleList {
4128
+ items: [Schedule!]!
4129
+ total: Int!
4130
+ }
4131
+
4132
+ input SchedulePatch {
4133
+ client: ScheduleClientInput!
4134
+ id: String
4135
+ name: String
4136
+ schedule: String
4137
+ task: ScheduleTaskInput!
4138
+ timezone: String
4139
+ type: String!
4140
+ }
4141
+
4142
+ type ScheduleTask {
4143
+ connection: ScheduleTaskConnection!
4144
+ data: Object!
4145
+ failed_policy: String!
4146
+ history_check: Boolean!
4147
+ max_retry_count: Int!
4148
+ retry_count: Int!
4149
+ retry_wait: Int!
4150
+ type: String!
4151
+ }
4152
+
4153
+ type ScheduleTaskConnection {
4154
+ headers: Object
4155
+ host: String
4156
+ topic: String
4157
+ }
4158
+
4159
+ input ScheduleTaskConnectionInput {
4160
+ headers: Object
4161
+ host: String
4162
+ topic: String
4163
+ }
4164
+
4165
+ input ScheduleTaskInput {
4166
+ connection: ScheduleTaskConnectionInput!
4167
+ data: Object!
4168
+ failed_policy: String!
4169
+ history_check: Boolean!
4170
+ max_retry_count: Int!
4171
+ retry_count: Int!
4172
+ retry_wait: Int!
4173
+ type: String!
4174
+ }
4175
+
4032
4176
  """Entity for Setting"""
4033
4177
  type Setting {
4034
4178
  category: String!
@@ -23,7 +23,9 @@ import {
23
23
  isTopMost,
24
24
  rowControlHandler,
25
25
  setCellBorder,
26
- WHERE
26
+ WHERE,
27
+ adjustCellWidth,
28
+ adjustCellHeight
27
29
  } from '../helper-functions'
28
30
 
29
31
  const NATURE: ComponentNature = {
@@ -43,6 +45,8 @@ const NATURE: ComponentNature = {
43
45
  }
44
46
 
45
47
  export default class DataList extends Container {
48
+ reflowing: boolean = false
49
+
46
50
  postrender(context: CanvasRenderingContext2D) {
47
51
  super.postrender(context)
48
52
 
@@ -111,68 +115,84 @@ export default class DataList extends Container {
111
115
  _onwheel(e: WheelEvent) {
112
116
  e.stopPropagation()
113
117
 
114
- var { height } = this.bounds
115
- var { offset = { x: 0, y: 0 } } = this.state
118
+ const { height } = this.bounds
119
+ const { offset = { x: 0, y: 0 } } = this.state
116
120
 
117
- var recordHeight = (this.heights[0] / this.heights.reduce((sum: number, height: number) => sum + height)) * height
121
+ const recordHeight = (this.heights[0] / this.heights.reduce((sum: number, height: number) => sum + height)) * height
118
122
 
119
- var minX = 0
120
- var minY = this.data && this.data.length ? Math.min(-recordHeight * this.data.length + height, 0) : 0
123
+ const minX = 0
124
+ const minY = this.data && this.data.length ? Math.min(-recordHeight * this.data.length + height, 0) : 0
121
125
 
122
- /* shiftKey + wheel deltaX 값을 변화시킨다. */
123
- if (e.deltaY == 0 && e.deltaX == 0) return
126
+ if (e.deltaY === 0 && e.deltaX === 0) return
124
127
 
125
- var x = e.deltaX + offset.x
126
- var y = -e.deltaY + offset.y
128
+ const x = e.deltaX + offset.x
129
+ const y = -e.deltaY + offset.y
127
130
 
128
- /* 휠을 밀면.. 화면은 위쪽으로 : scroll down */
129
- /* 휠을 당기면.. 화면은 아래쪽으로 : scroll up */
131
+ // 계산된 새로운 offset이 경계 내에 있는지 확인
132
+ const clampedX = Math.max(Math.min(0, x), minX)
133
+ const clampedY = Math.max(Math.min(0, y), minY)
130
134
 
131
- this.setState({
132
- offset: {
133
- x: Math.max(Math.min(0, x), minX),
134
- y: Math.max(Math.min(0, y), minY)
135
- }
136
- })
135
+ // offset이 실제로 변경되는 경우에만 preventDefault 호출
136
+ if (offset.x !== clampedX || offset.y !== clampedY) {
137
+ this.setState({
138
+ offset: {
139
+ x: clampedX,
140
+ y: clampedY
141
+ }
142
+ })
143
+
144
+ e.preventDefault() // 기본 동작 방지 (스크롤 막기)
145
+ }
137
146
  }
138
147
 
139
148
  private __START_OFFSET?: { x: number; y: number }
140
149
  private __START_Y?: number
141
150
 
142
- _ontouchstart(e: DragEvent) {
151
+ _ontouchstart(e: TouchEvent) {
152
+ e.stopPropagation()
153
+ // e.preventDefault()
154
+
143
155
  this.__START_OFFSET = this.state.offset || {
144
156
  x: 0,
145
157
  y: 0
146
158
  }
147
- this.__START_Y = e.offsetY
159
+ this.__START_Y = e.touches[0].clientY // 터치의 Y 좌표 저장
148
160
  }
149
161
 
150
- _ontouchmove(e: DragEvent) {
162
+ _ontouchmove(e: TouchEvent) {
163
+ e.stopPropagation()
164
+
151
165
  if (!this.__START_OFFSET) {
152
166
  return
153
167
  }
154
168
 
155
- var { height } = this.bounds
169
+ const { height } = this.bounds
170
+ const recordHeight = (this.heights[0] / this.heights.reduce((sum: number, height: number) => sum + height)) * height
171
+ const minY = this.data && this.data.length ? Math.min(-recordHeight * this.data.length + height, 0) : 0
172
+
173
+ const x = 0
174
+ const y = this.__START_OFFSET.y + (e.touches[0].clientY - this.__START_Y!) / this.rootModel.state.scale.y
156
175
 
157
- var recordHeight = (this.heights[0] / this.heights.reduce((sum: number, height: number) => sum + height)) * height
158
- var minY = this.data && this.data.length ? Math.min(-recordHeight * this.data.length + height, 0) : 0
176
+ // 새로운 offset 계산 경계 내로 클램핑
177
+ const clampedY = Math.max(Math.min(0, y), minY)
159
178
 
160
- var x = 0
161
- var y = this.__START_OFFSET.y + (e.offsetY - this.__START_Y!) / this.rootModel.state.scale.y
162
- y = Math.max(Math.min(0, y), minY)
179
+ const offset = this.state.offset || { x: 0, y: 0 }
163
180
 
164
- var offset = this.state.offset || { x: 0, y: 0 }
165
- if (offset.x !== x || offset.y !== y) {
181
+ // offset 실제로 변경될 있는 경우에만 preventDefault 호출
182
+ if (offset.y !== clampedY) {
166
183
  this.setState('offset', {
167
- x,
168
- y
184
+ x: 0,
185
+ y: clampedY
169
186
  })
170
187
 
171
- e.stopPropagation()
188
+ e.preventDefault() // 기본 동작 방지 (스크롤 막기)
172
189
  }
173
190
  }
174
191
 
175
- _ontouchend(e: DragEvent) {
192
+ _ontouchend(e: TouchEvent) {
193
+ e.stopPropagation()
194
+ // e.preventDefault()
195
+
176
196
  delete this.__START_OFFSET
177
197
  delete this.__START_Y
178
198
  }
@@ -291,6 +311,9 @@ export default class DataList extends Container {
291
311
  get eventMap() {
292
312
  return {
293
313
  '(self)': {
314
+ '(descendant)': {
315
+ change: this.oncellchanged
316
+ },
294
317
  '(all)': {
295
318
  wheel: this._onwheel,
296
319
  touchstart: this._ontouchstart,
@@ -301,6 +324,36 @@ export default class DataList extends Container {
301
324
  }
302
325
  }
303
326
 
327
+ oncellchanged(after: State, before: State, hint: { origin: Component }) {
328
+ if (this.reflowing) {
329
+ return
330
+ }
331
+
332
+ if ('width' in after) {
333
+ var diff = after.width - before.width
334
+ var index = this.components.indexOf(hint.origin)
335
+
336
+ if (index !== -1) {
337
+ adjustCellWidth(this, index % this.columns, diff)
338
+ }
339
+ }
340
+
341
+ if ('height' in after) {
342
+ var diff = after.height - before.height
343
+ var index = this.components.indexOf(hint.origin)
344
+
345
+ if (index !== -1) {
346
+ adjustCellHeight(this, 0, diff)
347
+ }
348
+ }
349
+ }
350
+
351
+ reflow() {
352
+ this.reflowing = true
353
+ super.reflow()
354
+ this.reflowing = false
355
+ }
356
+
304
357
  setCellsData() {
305
358
  if (!this.app.isViewMode) {
306
359
  return