@coffer-org/web 7.3.1 → 7.4.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.
Files changed (81) hide show
  1. package/dist/assets/ChatWidget-BW8sd6S7.js +5 -0
  2. package/dist/assets/DiagnosticsPage-3Ci43gZY.js +1 -0
  3. package/dist/assets/{GeoMap-B1DFGu6_.js → GeoMap-BQoT3_cw.js} +1 -1
  4. package/dist/assets/{MarkdownEditor-CANj53YF.js → MarkdownEditor-BYwRzrYg.js} +2 -2
  5. package/dist/assets/NewRecordView-BMaNGbcK.js +1 -0
  6. package/dist/assets/PluginSettingsPage-DA7ghBJP.js +1 -0
  7. package/dist/assets/ScanSummary-TlkBfsiq.js +1 -0
  8. package/dist/assets/SettingsForm-DMvn412d.js +1 -0
  9. package/dist/assets/SettingsPage-CTxF2X4G.js +3 -0
  10. package/dist/assets/ThemeSwitcher-Dd8tYTor.js +1 -0
  11. package/dist/assets/auth-context-Bo2wqUzm.js +1 -0
  12. package/dist/assets/{data-size-BMG0D59K.js → data-size-CO-LGHbN.js} +1 -1
  13. package/dist/assets/{extend-yQ8zoqGc.js → extend-CHOe1AVl.js} +1 -1
  14. package/dist/assets/{fields-CV3RQg0Y.js → fields-Ce51pRua.js} +1 -1
  15. package/dist/assets/{file-text-BdYRF4MO.js → file-text-CTdt_-uv.js} +1 -1
  16. package/dist/assets/{ilamy-view-Bb5692yT.js → ilamy-view-CCdCZX7g.js} +2 -2
  17. package/dist/assets/index-2id7xr9t.css +2 -0
  18. package/dist/assets/index-92nqE7hd.js +22 -0
  19. package/dist/assets/{input-BFMNMo6y.js → input-rjfudbd0.js} +1 -1
  20. package/dist/assets/{list-cache-DOhsI_p2.js → list-cache-wPeWyKg1.js} +1 -1
  21. package/dist/assets/phone-input-Dbuvvup1.js +1 -0
  22. package/dist/assets/{phone-input-8QtHMHO_.js → phone-input-u4b7_wtf.js} +2 -2
  23. package/dist/assets/popover-DCXlclK7.js +1 -0
  24. package/dist/assets/{registration-BBxYynR4.js → registration-43gjHJ3X.js} +1 -1
  25. package/dist/assets/settings-BEzSaRjz.js +1 -0
  26. package/dist/assets/{shelf-Cj_pNvd-.js → shelf-DjiUBfgQ.js} +1 -1
  27. package/dist/assets/{src-Q4BhkNtH.js → src-B-FFwJ-G.js} +1 -1
  28. package/dist/assets/{src-C46sbhiF.js → src-B1LWYTOR.js} +1 -1
  29. package/dist/assets/{src-B2aXBzDf.js → src-B7dY0wwO.js} +2 -2
  30. package/dist/assets/{src-Bhz_DXRd.js → src-BDP8FIN_.js} +1 -1
  31. package/dist/assets/{src-DnN2GqEI.js → src-BPuTgDYD.js} +1 -1
  32. package/dist/assets/{src-Bl8rYgUt2.js → src-BRP-DLVM2.js} +1 -1
  33. package/dist/assets/src-BU56fYCH2.js +1 -0
  34. package/dist/assets/src-B_6cwa-v.js +1 -0
  35. package/dist/assets/{src-qJ0szNVM.js → src-BmgYgIDb.js} +1 -1
  36. package/dist/assets/{src-DgQcfYnz.js → src-BpG7q6Ng.js} +1 -1
  37. package/dist/assets/{src-BrHtOaqX.js → src-C06O0ceD.js} +1 -1
  38. package/dist/assets/src-CCeQIMl_.js +1 -0
  39. package/dist/assets/{src-BHz-TcxU.js → src-CXEKm9OW.js} +1 -1
  40. package/dist/assets/{src-D14fQdLH.js → src-CbyyWbeT.js} +1 -1
  41. package/dist/assets/{src-CQOQ3BNT.js → src-CgXkpslu.js} +1 -1
  42. package/dist/assets/{src-tKMBP4Dv.js → src-CtQWxdaS.js} +1 -1
  43. package/dist/assets/src-DDtMlZ03.js +1 -0
  44. package/dist/assets/{src-rMuD7zD4.js → src-DNx0vmvI.js} +1 -1
  45. package/dist/assets/src-DfQ6cuPE.js +7 -0
  46. package/dist/assets/{src-4bmZI2h_.js → src-DjrjxzQu.js} +1 -1
  47. package/dist/assets/{src-CE1TPDES.js → src-Dsh4Yd_x.js} +1 -1
  48. package/dist/assets/{src-xh_qAK43.js → src-Du26RLvk.js} +1 -1
  49. package/dist/assets/{src-BmyfVP9z.js → src-aPsTM6Fr.js} +1 -1
  50. package/dist/assets/{src-0TBpEeKK.js → src-iJXhTwKd.js} +1 -1
  51. package/dist/assets/{src-Dr_dOgc9.js → src-rXsbV4Ce.js} +1 -1
  52. package/dist/assets/ui-9Rp0TqUO.js +2 -0
  53. package/dist/assets/ui-ByltCpi4.js +2 -0
  54. package/dist/assets/ui-CFyjU_NB.js +2 -0
  55. package/dist/assets/ui-S_PopF4y.js +2 -0
  56. package/dist/index.html +14 -14
  57. package/dist-vendor/web-ui.js +12374 -12272
  58. package/package.json +1 -1
  59. package/dist/assets/ChatWidget-vl_ApeDr.js +0 -5
  60. package/dist/assets/DiagnosticsPage-DVAqVVLa.js +0 -1
  61. package/dist/assets/NewRecordView-Y6PoWPB9.js +0 -1
  62. package/dist/assets/PluginSettingsPage-d0LhYfXE.js +0 -1
  63. package/dist/assets/ScanSummary-xxY2oZVM.js +0 -1
  64. package/dist/assets/SettingsForm-ChaqrcJM.js +0 -1
  65. package/dist/assets/SettingsPage-4_Gqty1-.js +0 -3
  66. package/dist/assets/ThemeSwitcher-eMEFNoJq.js +0 -1
  67. package/dist/assets/auth-context-CoCE5oPD.js +0 -1
  68. package/dist/assets/index-Brc5FUYA.css +0 -2
  69. package/dist/assets/index-C98p9ash.js +0 -22
  70. package/dist/assets/phone-input-3xV95mM6.js +0 -1
  71. package/dist/assets/popover-UkAmHo3Y.js +0 -1
  72. package/dist/assets/settings-Bo5IOwVg.js +0 -1
  73. package/dist/assets/src-B0pL3dGf.js +0 -7
  74. package/dist/assets/src-BZK1QVol.js +0 -1
  75. package/dist/assets/src-CD1zBxk2.js +0 -1
  76. package/dist/assets/src-Ds6m7Evp2.js +0 -1
  77. package/dist/assets/src-Mln-mCD3.js +0 -1
  78. package/dist/assets/ui-3phlsSm1.js +0 -2
  79. package/dist/assets/ui-B21VM1St.js +0 -2
  80. package/dist/assets/ui-BfN7X5UB.js +0 -2
  81. package/dist/assets/ui-DxLuYjTk.js +0 -2
@@ -1 +1 @@
1
- import{n as e,r as t}from"./fields-CV3RQg0Y.js";import{a as n}from"./shelf-Cj_pNvd-.js";import{i as r,n as i}from"./plugin-Cjr7lgQH.js";import{t as a}from"./extend-yQ8zoqGc.js";import{t as o}from"./showcase-BeBnutzT.js";var s=a({id:`drone`,label:`drone.drone.label`,icon:`tb:drone`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`aircraft`,`rtf`]}},agent:{description:`FPV drone technical characteristics. frame_size — frame size (e.g. 3.5"). motors — motors. firmware — firmware (Betaflight/INAV). camera/flight_controller/vtx/gps_module link to things/item[type=drone] records of the matching subtype. A drone whose parts cannot be separate records is subtype='rtf' instead, and carries the component extends directly.`,instructions:`drone references the components; specs live in each module's fields. When you replace a component or update the firmware — update the relevant fields via update_record.`},fields:{bento:e.bento({fields:{group:{span:`2x1`,el:e.group({scope:`hoist`,fields:{motors:e.string({label:`drone.drone.fields.motors`,rules:{max:150}}),props:e.string({label:`drone.drone.fields.props`,rules:{max:80}}),camera:e.relation({label:`drone.drone.fields.camera`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`camera`}})})}})},group2:e.group({scope:`hoist`,fields:{power_module:e.string({label:`drone.drone.fields.power_module`,rules:{max:60}}),vtx:e.relation({label:`drone.drone.fields.vtx`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`vtx`}})})}}),group3:e.group({scope:`hoist`,fields:{flight_time:e.string({label:`drone.drone.fields.flight_time`,rules:{max:60}}),firmware:e.string({label:`drone.drone.fields.firmware`,options:`drone-firmware`,strict:!0,noSearch:!0}),firmware_version:e.string({label:`drone.drone.fields.firmware_version`,rules:{max:40}}),firmware_target:e.string({label:`drone.drone.fields.firmware_target`,rules:{max:80}})}}),group4:e.group({scope:`hoist`,fields:{frame_size:e.string({label:`drone.drone.fields.frame_size`,rules:{max:40}}),purpose:e.string({label:`drone.drone.fields.purpose`,rules:{max:200}})}}),group5:e.group({scope:`hoist`,fields:{flight_controller:e.relation({label:`drone.drone.fields.flight_controller`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`flight_controller`}})}),gps_module:e.relation({label:`drone.drone.fields.gps_module`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`gps`}})})}}),group6:e.group({scope:`hoist`,fields:{radio_link:e.string({label:`drone.drone.fields.radio_link`,options:`drone-radio-links`,multiple:!0,strict:!0,noSearch:!0}),receiver:e.string({label:`drone.drone.fields.receiver`,rules:{max:80}}),video_system:e.string({label:`drone.drone.fields.video_system`,options:`drone-video-systems`,strict:!0,noSearch:!0})}})}}),snippets:e.group({scope:`nest`,label:`drone.drone.groups.snippets`,icon:`lucide:terminal`,multiple:!0,fields:{title:e.string({label:`drone.drone.fields.snippet_title`,rules:{max:100}}),summary:e.text({label:`drone.drone.fields.snippet_summary`,rules:{max:500}}),snippet:e.source({label:`drone.drone.fields.snippet`,rules:{ext:`md`}})}}),flights:e.backrefs({label:`drone.drone.fields.flights`,from:{library:`drone`,shelf:`flight`,field:`aircraft`}}),notes:e.text({label:`drone.drone.fields.notes`,rules:{max:2e3}})}}),c=a({id:`drone_battery`,label:`drone.drone_battery.label`,icon:`lucide:battery-full`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`battery`,`rtf`]}},agent:`FPV drone battery characteristics. cells — number of cells (1S/3S/4S). capacity — capacity in mAh. c_rate — discharge current. auw — all-up weight of the assembly in flight.`,fields:{charger:e.string({label:`drone.drone_battery.fields.charger`,rules:{max:100}}),cells:e.string({label:`drone.drone_battery.fields.cells`,options:`drone-cells`,strict:!0,noSearch:!0}),capacity:e.measured({label:`drone.drone_battery.fields.capacity`,units:`energy`}),c_rate:e.string({label:`drone.drone_battery.fields.c_rate`,rules:{max:20}}),auw:e.string({label:`drone.drone_battery.fields.auw`,rules:{max:40}}),flights:e.backrefs({label:`drone.drone_battery.fields.flights`,from:{library:`drone`,shelf:`flight`,field:`batteries`}}),notes:e.text({label:`drone.drone_battery.fields.notes`,rules:{max:2e3}})}}),l=a({id:`drone_vtx`,label:`drone.drone_vtx.label`,icon:`lucide:radio-tower`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`vtx`,`rtf`]}},agent:`FPV video transmitter characteristics. input_voltage — input voltage. protocol — control protocols, codes from the drone-vtx-protocols list. frequency_groups — Betaflight band letters. channel_count — number of channels.`,fields:{input_voltage:e.string({label:`drone.drone_vtx.fields.input_voltage`,rules:{max:40}}),protocol:e.string({label:`drone.drone_vtx.fields.protocol`,options:`drone-vtx-protocols`,multiple:!0,strict:!0,noSearch:!0}),antenna_interface:e.string({label:`drone.drone_vtx.fields.antenna_interface`,options:`drone-rf-connectors`,strict:!0,noSearch:!0}),channel_count:e.int({label:`drone.drone_vtx.fields.channel_count`,rules:{min:0}}),mounting:e.string({label:`drone.drone_vtx.fields.mounting`,options:`drone-mounting`,multiple:!0,strict:!0,noSearch:!0}),built_in_microphone:e.boolean({label:`drone.drone_vtx.fields.built_in_microphone`}),frequency_groups:e.string({label:`drone.drone_vtx.fields.frequency_groups`,options:`drone-bands`,multiple:!0,strict:!0,noSearch:!0}),power_levels:e.keyed({label:`drone.drone_vtx.groups.power_levels`,icon:`lucide:zap`,container:e.row,fields:{level:e.string({label:`drone.drone_vtx.fields.power_level`,options:`drone-vtx-power`,strict:!0,noSearch:!0}),current_ma:e.int({label:`drone.drone_vtx.fields.current_ma`,rules:{min:0}}),dbm:e.real({label:`drone.drone_vtx.fields.dbm`})},by:`level`}),notes:e.text({label:`drone.drone_vtx.fields.notes`,rules:{max:2e3}})}}),u=a({id:`drone_gps`,label:`drone.drone_gps.label`,icon:`lucide:satellite`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`gps`,`rtf`]}},agent:`FPV drone GPS module characteristics. gnss_chip — chipset. compass_chip — magnetometer. satellite_systems — supported satellite systems.`,fields:{gnss_chip:e.string({label:`drone.drone_gps.fields.gnss_chip`,rules:{max:80}}),compass_chip:e.string({label:`drone.drone_gps.fields.compass_chip`,rules:{max:60}}),barometer:e.boolean({label:`drone.drone_gps.fields.barometer`}),interface:e.string({label:`drone.drone_gps.fields.interface`,options:`drone-serial-interfaces`,multiple:!0,strict:!0,noSearch:!0}),input_voltage:e.string({label:`drone.drone_gps.fields.input_voltage`,rules:{max:40}}),update_rate_hz:e.int({label:`drone.drone_gps.fields.update_rate_hz`,rules:{min:0}}),receiving_channels:e.int({label:`drone.drone_gps.fields.receiving_channels`,rules:{min:0}}),supported_protocols:e.string({label:`drone.drone_gps.fields.supported_protocols`,options:`drone-gnss-protocols`,multiple:!0,strict:!0,noSearch:!0}),baud_rates:e.string({label:`drone.drone_gps.fields.baud_rates`,options:`drone-baud-rates`,multiple:!0,strict:!0,noSearch:!0}),satellite_systems:e.string({label:`drone.drone_gps.fields.satellite_systems`,options:`drone-gnss-systems`,multiple:!0,strict:!0,noSearch:!0}),notes:e.text({label:`drone.drone_gps.fields.notes`,rules:{max:2e3}})}}),d=a({id:`drone_flight_controller`,label:`drone.drone_flight_controller.label`,icon:`lucide:sliders-horizontal`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`flight_controller`,`rtf`]}},agent:`FPV drone flight controller characteristics. mcu — processor (STM32F411/F405). gyro — gyroscope. supported_firmware — compatible firmware (Betaflight, INAV).`,fields:{mcu:e.string({label:`drone.drone_flight_controller.fields.mcu`,options:`drone-fc-mcu`,strict:!0,noSearch:!0}),gyro:e.string({label:`drone.drone_flight_controller.fields.gyro`,options:`drone-gyro`,multiple:!0,strict:!0,noSearch:!0}),barometer:e.boolean({label:`drone.drone_flight_controller.fields.barometer`}),osd_chip:e.string({label:`drone.drone_flight_controller.fields.osd_chip`,options:`drone-osd-chip`,strict:!0,noSearch:!0}),blackbox:e.string({label:`drone.drone_flight_controller.fields.blackbox`,options:`drone-blackbox`,strict:!0,noSearch:!0}),bluetooth:e.boolean({label:`drone.drone_flight_controller.fields.bluetooth`}),wifi:e.boolean({label:`drone.drone_flight_controller.fields.wifi`}),current_sensor_input:e.boolean({label:`drone.drone_flight_controller.fields.current_sensor_input`}),power_input:e.string({label:`drone.drone_flight_controller.fields.power_input`,rules:{max:40}}),constant_current:e.string({label:`drone.drone_flight_controller.fields.constant_current`,rules:{max:20}}),peak_current:e.string({label:`drone.drone_flight_controller.fields.peak_current`,rules:{max:20}}),bec_5v:e.string({label:`drone.drone_flight_controller.fields.bec_5v`,rules:{max:20}}),bec_9v:e.string({label:`drone.drone_flight_controller.fields.bec_9v`,rules:{max:20}}),mounting:e.string({label:`drone.drone_flight_controller.fields.mounting`,options:`drone-mounting`,multiple:!0,strict:!0,noSearch:!0}),uart_count:e.int({label:`drone.drone_flight_controller.fields.uart_count`,rules:{min:0}}),supported_firmware:e.string({label:`drone.drone_flight_controller.fields.supported_firmware`,options:`drone-firmware`,multiple:!0,strict:!0,noSearch:!0}),firmware_target:e.string({label:`drone.drone_flight_controller.fields.firmware_target`,rules:{max:80}}),build_role:e.string({label:`drone.drone_flight_controller.fields.build_role`,rules:{max:200}}),notes:e.text({label:`drone.drone_flight_controller.fields.notes`,rules:{max:2e3}})}}),f=a({id:`drone_goggles`,label:`drone.drone_goggles.label`,icon:`lucide:glasses`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:`goggles`},agent:`FPV goggles characteristics. display_size — display diagonal. frequency_bands — supported radio bands. battery_life — runtime on battery.`,fields:{display_size:e.string({label:`drone.drone_goggles.fields.display_size`,rules:{max:20}}),display_resolution:e.string({label:`drone.drone_goggles.fields.display_resolution`,rules:{max:40}}),display_brightness:e.string({label:`drone.drone_goggles.fields.display_brightness`,rules:{max:30}}),view_angle:e.string({label:`drone.drone_goggles.fields.view_angle`,rules:{max:20}}),antenna:e.string({label:`drone.drone_goggles.fields.antenna`,rules:{max:80}}),frequency_bands:e.string({label:`drone.drone_goggles.fields.frequency_bands`,options:`drone-bands`,multiple:!0,strict:!0,noSearch:!0}),battery:e.string({label:`drone.drone_goggles.fields.battery`,rules:{max:60}}),battery_life:e.string({label:`drone.drone_goggles.fields.battery_life`,rules:{max:40}}),charging:e.string({label:`drone.drone_goggles.fields.charging`,rules:{max:60}}),band_channels:e.keyed({label:`drone.drone_goggles.groups.band_channels`,icon:`lucide:radio`,container:e.row,fields:{band:e.string({label:`drone.drone_goggles.fields.band`,options:`drone-bands`,strict:!0,noSearch:!0}),channels:e.int({label:`drone.drone_goggles.fields.channels`,multiple:!0})},by:`band`}),notes:e.text({label:`drone.drone_goggles.fields.notes`,rules:{max:2e3}})}}),p=a({id:`drone_antenna`,label:`drone.drone_antenna.label`,icon:`lucide:radio`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`antenna`,`rtf`]}},agent:`FPV antenna characteristics. rf_band — the bands it covers, codes from drone-rf-bands. polarization — RHCP/LHCP/linear; a video link needs the SAME polarization on both ends. antenna_type — the radiating structure. connector — one model often ships in several connector variants.`,fields:{rf_band:e.string({label:`drone.drone_antenna.fields.rf_band`,options:`drone-rf-bands`,multiple:!0,strict:!0,noSearch:!0}),polarization:e.string({label:`drone.drone_antenna.fields.polarization`,options:`drone-polarization`,strict:!0,noSearch:!0}),antenna_type:e.string({label:`drone.drone_antenna.fields.antenna_type`,options:`drone-antenna-types`,strict:!0,noSearch:!0}),connector:e.string({label:`drone.drone_antenna.fields.connector`,options:`drone-rf-connectors`,multiple:!0,strict:!0,noSearch:!0}),gain_dbi:e.real({label:`drone.drone_antenna.fields.gain_dbi`}),cable_length:e.int({label:`drone.drone_antenna.fields.cable_length`,rules:{min:0}}),notes:e.text({label:`drone.drone_antenna.fields.notes`,rules:{max:2e3}})}}),m=a({id:`drone_receiver`,label:`drone.drone_receiver.label`,icon:`lucide:antenna`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`receiver`,`rtf`]}},agent:`RC receiver characteristics. radio_link — the protocol it binds with (ExpressLRS, Crossfire…). output_protocol — how it talks to the flight controller (CRSF, SBUS…). diversity — two antennas with active switching.`,fields:{radio_link:e.string({label:`drone.drone_receiver.fields.radio_link`,options:`drone-radio-links`,strict:!0,noSearch:!0}),rf_band:e.string({label:`drone.drone_receiver.fields.rf_band`,options:`drone-rf-bands`,multiple:!0,strict:!0,noSearch:!0}),output_protocol:e.string({label:`drone.drone_receiver.fields.output_protocol`,options:`drone-rx-outputs`,multiple:!0,strict:!0,noSearch:!0}),antenna_connector:e.string({label:`drone.drone_receiver.fields.antenna_connector`,options:`drone-rf-connectors`,strict:!0,noSearch:!0}),antenna_count:e.int({label:`drone.drone_receiver.fields.antenna_count`,rules:{min:0}}),telemetry:e.boolean({label:`drone.drone_receiver.fields.telemetry`}),diversity:e.boolean({label:`drone.drone_receiver.fields.diversity`}),input_voltage:e.string({label:`drone.drone_receiver.fields.input_voltage`,rules:{max:40}}),firmware_version:e.string({label:`drone.drone_receiver.fields.firmware_version`,rules:{max:40}}),notes:e.text({label:`drone.drone_receiver.fields.notes`,rules:{max:2e3}})}}),h=a({id:`drone_camera`,label:`drone.drone_camera.label`,icon:`lucide:camera`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`camera`,`rtf`]}},agent:`FPV camera characteristics. sensor — the sensor model (free text, e.g. Sony Super HAD II). resolution_tvl — analog horizontal resolution in TVL. aspect_ratio — 4:3 / 16:9 / switchable. output — the video signal it produces (analog CVBS or a digital HD system).`,fields:{sensor:e.string({label:`drone.drone_camera.fields.sensor`,rules:{max:100}}),resolution_tvl:e.int({label:`drone.drone_camera.fields.resolution_tvl`,rules:{min:0}}),aspect_ratio:e.string({label:`drone.drone_camera.fields.aspect_ratio`,options:`drone-camera-aspect`,strict:!0,noSearch:!0}),lens_mm:e.real({label:`drone.drone_camera.fields.lens_mm`}),fov_deg:e.int({label:`drone.drone_camera.fields.fov_deg`,rules:{min:0}}),output:e.string({label:`drone.drone_camera.fields.output`,options:`drone-camera-output`,strict:!0,noSearch:!0}),camera_size:e.string({label:`drone.drone_camera.fields.camera_size`,options:`drone-camera-sizes`,strict:!0,noSearch:!0}),input_voltage:e.string({label:`drone.drone_camera.fields.input_voltage`,rules:{max:40}}),notes:e.text({label:`drone.drone_camera.fields.notes`,rules:{max:2e3}})}}),g=[`ok`,`low_voltage`,`crash`,`lost`],_=[{value:`ok`,title:`drone.options.outcome.ok`,tone:`success`},{value:`low_voltage`,title:`drone.options.outcome.low_voltage`,tone:`warning`},{value:`crash`,title:`drone.options.outcome.crash`,tone:`danger`},{value:`lost`,title:`drone.options.outcome.lost`,tone:`danger`}],v=e=>Array.isArray(e)?e.filter(e=>e&&typeof e==`object`):[];function y(e,t){let n=[];for(let r of v(e)){let e=r[t];if(e==null||e===``)continue;let i=Number(e);Number.isFinite(i)&&(n.includes(i)||n.push(i))}return n}function b(e,t=`outcome`){let n=-1;for(let r of v(e)){let e=g.indexOf(r[t]);e>n&&(n=e)}return n<0?null:g[n]}var x=n({shelf:`flight`,library:`drone`,label:`drone.flight.label`,icon:`lucide:plane-takeoff`,agent:"A flying session, not a single sortie: one record is one outing — date, place, aircraft — and each battery pack flown is a row of `packs` (battery, duration in seconds, outcome, notes). `batteries` and `outcome` are SERVER-OWNED derivations over those rows and are rejected if sent: `batteries` indexes the distinct batteries used, `outcome` is the worst row outcome. Record a crash by setting that pack's outcome and listing the broken parts in `damage`, not by prose in `notes`. The `aircraft` picker only offers things/item[subtype='aircraft'] — a ready-to-fly kit (subtype='rtf') cannot be selected there today, so log its flights against an 'aircraft'-subtype record instead.",views:{title:`date`,listKind:`map`,list:[`aircraft`,`place`,`outcome`],inline:[`date`,`aircraft`]},fields:{date:e.date({label:`drone.flight.fields.date`,rules:{min:`2000-01-01`,max:`today`},ui:{span:4}}),description:e.text({label:`drone.flight.fields.description`,rules:{max:1e3}}),place:e.geo({label:`drone.flight.fields.place`}),aircraft:e.relation({label:`drone.flight.fields.aircraft`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`aircraft`}})}),batteries:e.relation({label:`drone.flight.fields.batteries`,multiple:!0,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`battery`}}),value:({record:e})=>y(e.packs,`battery`)}),weather:e.group({scope:`hoist`,label:`drone.flight.groups.weather`,icon:`lucide:cloud-sun`,fields:{temp:e.measured({label:`drone.flight.fields.temp`,units:`temperature`,ui:{span:4}}),wind:e.measured({label:`drone.flight.fields.wind`,units:`speed`,ui:{span:4}}),sky:e.string({label:`drone.flight.fields.sky`,options:`drone-sky`,strict:!0,noSearch:!0})}}),packs:e.row({scope:`nest`,multiple:!0,label:`drone.flight.fields.packs`,icon:`lucide:battery-charging`,fields:{battery:e.relation({label:`drone.flight.fields.battery`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`battery`}}),mutate:[`batteries`]}),duration:e.duration({label:`drone.flight.fields.duration`}),outcome:e.string({label:`drone.flight.fields.pack_outcome`,options:`drone-outcomes`,strict:!0,noSearch:!0,mutate:[`outcome`]}),notes:e.text({label:`drone.flight.fields.pack_notes`,rules:{max:500}})}}),outcome:e.string({label:`drone.flight.fields.outcome`,options:`drone-outcomes`,strict:!0,noSearch:!0,value:({record:e})=>b(e.packs)}),setup:e.group({scope:`hoist`,label:`drone.flight.groups.setup`,icon:`lucide:sliders-horizontal`,fields:{firmware_version:e.string({label:`drone.flight.fields.firmware_version`,rules:{max:40}}),tune:e.text({label:`drone.flight.fields.tune`,rules:{max:2e3}})}}),damage:e.relation({label:`drone.flight.fields.damage`,multiple:!0,options:t({library:`things`,shelf:`item`,filter:{type:`drone`}})}),video:e.video({label:`drone.flight.fields.video`,multiple:!0}),photos:e.image({label:`drone.flight.fields.photos`,multiple:!0}),edit_link:e.link({label:`drone.flight.fields.edit_link`}),tags:e.tags({label:`drone.flight.fields.tags`}),notes:e.text({label:`drone.flight.fields.notes`,rules:{max:2e3}})}}),S=i({id:`drone`,version:`1.0.0`,dependsOn:[`things`,`geo`],label:`drone.plugin.label`,description:`drone.plugin.description`,libraries:[{meta:r({id:`drone`,label:`drone.library.label`,icon:`tb:drone`,agent:`FPV drones and their components. A component is a things/item row with type=drone — this library owns no table for those. A FLIGHT is different: it is an event, not a thing, and it is this library's one table (flight): one record per outing, with the battery packs flown as rows inside it.`}),shelves:[x]}],extends_:[s,c,l,u,d,f,p,m,h],showcases:[o({id:`fleet`,library:`drone`,label:`drone.fleet.label`,icon:`lucide:plane`,source:{library:`things`,shelf:`item`},filter:{type:`drone`},columns:[`subtype`,`brand`,`model`,`location`,`condition`],defaultGroupBy:`subtype`,createDefaults:{type:`drone`}})],optionLists:[{name:`drone-bands`,options:[{value:`A`,title:`A`},{value:`B`,title:`B`},{value:`E`,title:`E`},{value:`F`,title:`F`},{value:`R`,title:`R`},{value:`L`,title:`L`},{value:`U`,title:`U`},{value:`O`,title:`O`},{value:`H`,title:`H`}]},{name:`drone-vtx-power`,options:[{value:`pit`,title:`PIT`},{value:`25mw`,title:`25 mW`},{value:`100mw`,title:`100 mW`},{value:`200mw`,title:`200 mW`},{value:`350mw`,title:`350 mW`},{value:`400mw`,title:`400 mW`},{value:`600mw`,title:`600 mW`},{value:`800mw`,title:`800 mW`},{value:`1000mw`,title:`1 W`},{value:`1600mw`,title:`1.6 W`},{value:`2500mw`,title:`2.5 W`}]},{name:`drone-vtx-protocols`,options:[{value:`smartaudio_1_0`,title:`SmartAudio 1.0`},{value:`smartaudio_2_0`,title:`SmartAudio 2.0`},{value:`smartaudio_2_1`,title:`SmartAudio 2.1`},{value:`tramp`,title:`IRC Tramp`},{value:`msp_displayport`,title:`MSP DisplayPort`},{value:`none`,title:`drone.options.none`}]},{name:`drone-rf-connectors`,options:[{value:`ipex_mhf1`,title:`IPEX / MHF1 (U.FL)`},{value:`ipex_mhf3`,title:`IPEX MHF3`},{value:`mmcx`,title:`MMCX`},{value:`sma`,title:`SMA`},{value:`rp_sma`,title:`RP-SMA`},{value:`ufl_solder`,title:`U.FL (soldered)`}]},{name:`drone-mounting`,options:[{value:`16x16_m2`,title:`16×16 mm M2`},{value:`20x20_m2`,title:`20×20 mm M2`},{value:`20x20_m3`,title:`20×20 mm M3`},{value:`25.5x25.5_m2`,title:`25.5×25.5 mm M2`},{value:`30.5x30.5_m3`,title:`30.5×30.5 mm M3`},{value:`adhesive`,title:`drone.options.adhesive`}]},{name:`drone-firmware`,options:[{value:`betaflight`,title:`Betaflight`},{value:`inav`,title:`INAV`},{value:`ardupilot`,title:`ArduPilot`},{value:`emuflight`,title:`EmuFlight`},{value:`rotorflight`,title:`Rotorflight`},{value:`kiss`,title:`KISS`},{value:`cleanflight`,title:`Cleanflight`}]},{name:`drone-fc-mcu`,options:[{value:`stm32f411`,title:`STM32F411`},{value:`stm32f405`,title:`STM32F405`},{value:`stm32f722`,title:`STM32F722`},{value:`stm32f745`,title:`STM32F745`},{value:`stm32f765`,title:`STM32F765`},{value:`stm32h743`,title:`STM32H743`},{value:`stm32h750`,title:`STM32H750`},{value:`at32f435`,title:`AT32F435`},{value:`gd32f405`,title:`GD32F405`}]},{name:`drone-gyro`,options:[{value:`mpu6000`,title:`MPU6000`},{value:`mpu6500`,title:`MPU6500`},{value:`icm20602`,title:`ICM20602`},{value:`icm20689`,title:`ICM20689`},{value:`icm42688p`,title:`ICM42688-P`},{value:`icm42605`,title:`ICM42605`},{value:`bmi270`,title:`BMI270`},{value:`bmi160`,title:`BMI160`}]},{name:`drone-osd-chip`,options:[{value:`at7456e`,title:`AT7456E`},{value:`max7456`,title:`MAX7456`},{value:`msp_displayport`,title:`MSP DisplayPort`},{value:`none`,title:`drone.options.none`}]},{name:`drone-blackbox`,options:[{value:`none`,title:`drone.options.none`},{value:`flash_8mb`,title:`Flash 8 MB`},{value:`flash_16mb`,title:`Flash 16 MB`},{value:`flash_32mb`,title:`Flash 32 MB`},{value:`sd_card`,title:`microSD`}]},{name:`drone-gnss-systems`,options:[{value:`gps`,title:`GPS`},{value:`glonass`,title:`GLONASS`},{value:`galileo`,title:`Galileo`},{value:`beidou`,title:`BeiDou`},{value:`qzss`,title:`QZSS`},{value:`sbas`,title:`SBAS`},{value:`navic`,title:`NavIC`}]},{name:`drone-gnss-protocols`,options:[{value:`ubx`,title:`UBX`},{value:`nmea`,title:`NMEA`},{value:`rtcm3`,title:`RTCM3`},{value:`msp`,title:`MSP`}]},{name:`drone-baud-rates`,options:[{value:`4800`,title:`4800`},{value:`9600`,title:`9600`},{value:`19200`,title:`19200`},{value:`38400`,title:`38400`},{value:`57600`,title:`57600`},{value:`115200`,title:`115200`},{value:`230400`,title:`230400`},{value:`460800`,title:`460800`},{value:`921600`,title:`921600`}]},{name:`drone-serial-interfaces`,options:[{value:`uart`,title:`UART`},{value:`i2c`,title:`I2C`},{value:`spi`,title:`SPI`},{value:`can`,title:`CAN`}]},{name:`drone-video-systems`,options:[{value:`analog_5_8`,title:`drone.options.videoSystems.analog_5_8`},{value:`dji_v1_v2`,title:`DJI V1/V2`},{value:`dji_o3`,title:`DJI O3`},{value:`dji_o4`,title:`DJI O4`},{value:`walksnail_avatar`,title:`Walksnail Avatar`},{value:`hdzero`,title:`HDZero`}]},{name:`drone-radio-links`,options:[{value:`elrs_2_4`,title:`ExpressLRS 2.4 GHz`},{value:`elrs_900`,title:`ExpressLRS 868/915 MHz`},{value:`crossfire`,title:`TBS Crossfire`},{value:`tracer`,title:`TBS Tracer`},{value:`ghost`,title:`ImmersionRC Ghost`},{value:`frsky_d16`,title:`FrSky D16`},{value:`frsky_d8`,title:`FrSky D8`},{value:`dsmx`,title:`Spektrum DSMX`},{value:`dji`,title:`DJI`}]},{name:`drone-rf-bands`,options:[{value:`5_8ghz`,title:`5.8 GHz`},{value:`2_4ghz`,title:`2.4 GHz`},{value:`1_2ghz`,title:`1.2 GHz`},{value:`900mhz`,title:`868/915 MHz`},{value:`433mhz`,title:`433 MHz`}]},{name:`drone-polarization`,options:[{value:`rhcp`,title:`drone.options.polarization.rhcp`},{value:`lhcp`,title:`drone.options.polarization.lhcp`},{value:`linear`,title:`drone.options.polarization.linear`}]},{name:`drone-antenna-types`,options:[{value:`omni`,title:`drone.options.antennaTypes.omni`},{value:`patch`,title:`drone.options.antennaTypes.patch`},{value:`helical`,title:`drone.options.antennaTypes.helical`},{value:`pagoda`,title:`drone.options.antennaTypes.pagoda`},{value:`cloverleaf`,title:`drone.options.antennaTypes.cloverleaf`},{value:`monopole`,title:`drone.options.antennaTypes.monopole`},{value:`whip`,title:`drone.options.antennaTypes.whip`}]},{name:`drone-cells`,options:[{value:`1s`,title:`1S`},{value:`2s`,title:`2S`},{value:`3s`,title:`3S`},{value:`4s`,title:`4S`},{value:`5s`,title:`5S`},{value:`6s`,title:`6S`},{value:`7s`,title:`7S`},{value:`8s`,title:`8S`},{value:`12s`,title:`12S`}]},{name:`drone-rx-outputs`,options:[{value:`crsf`,title:`CRSF`},{value:`sbus`,title:`SBUS`},{value:`ibus`,title:`IBUS`},{value:`ppm`,title:`PPM`},{value:`pwm`,title:`PWM`},{value:`spektrum`,title:`Spektrum`},{value:`ghst`,title:`GHST`}]},{name:`drone-camera-aspect`,options:[{value:`4_3`,title:`4:3`},{value:`16_9`,title:`16:9`},{value:`switchable`,title:`drone.options.cameraAspect.switchable`}]},{name:`drone-camera-output`,options:[{value:`analog_cvbs`,title:`drone.options.cameraOutput.analog_cvbs`},{value:`dji`,title:`DJI`},{value:`walksnail`,title:`Walksnail`},{value:`hdzero`,title:`HDZero`}]},{name:`drone-camera-sizes`,options:[{value:`nano`,title:`Nano`},{value:`micro`,title:`Micro`},{value:`mini`,title:`Mini`},{value:`full`,title:`Full-size`},{value:`whoop`,title:`Whoop`}]},{name:`drone-outcomes`,options:[..._]},{name:`drone-sky`,options:[{value:`clear`,title:`drone.options.sky.clear`},{value:`cloudy`,title:`drone.options.sky.cloudy`},{value:`overcast`,title:`drone.options.sky.overcast`},{value:`fog`,title:`drone.options.sky.fog`},{value:`rain`,title:`drone.options.sky.rain`},{value:`snow`,title:`drone.options.sky.snow`}]}],fieldContribs:[{library:`things`,shelf:`item`,field:`type`,options:[{value:`drone`,title:`drone.drone.label`}]},{library:`things`,shelf:`item`,field:`subtype`,options:[{value:`aircraft`,title:`drone.contrib.subtype.aircraft`,when:{type:`drone`}},{value:`battery`,title:`drone.drone_battery.label`,when:{type:`drone`}},{value:`vtx`,title:`drone.drone_vtx.label`,when:{type:`drone`}},{value:`gps`,title:`drone.drone_gps.label`,when:{type:`drone`}},{value:`flight_controller`,title:`drone.drone_flight_controller.label`,when:{type:`drone`}},{value:`goggles`,title:`drone.drone_goggles.label`,when:{type:`drone`}},{value:`radio`,title:`drone.contrib.subtype.radio`,when:{type:`drone`}},{value:`camera`,title:`drone.drone_camera.label`,when:{type:`drone`}},{value:`antenna`,title:`drone.drone_antenna.label`,when:{type:`drone`}},{value:`receiver`,title:`drone.drone_receiver.label`,when:{type:`drone`}},{value:`frame`,title:`drone.contrib.subtype.frame`,when:{type:`drone`}},{value:`rtf`,title:`drone.contrib.subtype.rtf`,when:{type:`drone`}},{value:`accessory`,title:`drone.contrib.subtype.accessory`,when:{type:`drone`}}]}]});export{S as default};
1
+ import{n as e,r as t}from"./fields-Ce51pRua.js";import{a as n}from"./shelf-DjiUBfgQ.js";import{i as r,n as i}from"./plugin-Cjr7lgQH.js";import{t as a}from"./extend-CHOe1AVl.js";import{t as o}from"./showcase-BeBnutzT.js";var s=a({id:`drone`,label:`drone.drone.label`,icon:`tb:drone`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`aircraft`,`rtf`]}},agent:{description:`FPV drone technical characteristics. frame_size — frame size (e.g. 3.5"). motors — motors. firmware — firmware (Betaflight/INAV). camera/flight_controller/vtx/gps_module link to things/item[type=drone] records of the matching subtype. A drone whose parts cannot be separate records is subtype='rtf' instead, and carries the component extends directly.`,instructions:`drone references the components; specs live in each module's fields. When you replace a component or update the firmware — update the relevant fields via update_record.`},fields:{bento:e.bento({fields:{group:{span:`2x1`,el:e.group({scope:`hoist`,fields:{motors:e.string({label:`drone.drone.fields.motors`,rules:{max:150}}),props:e.string({label:`drone.drone.fields.props`,rules:{max:80}}),camera:e.relation({label:`drone.drone.fields.camera`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`camera`}})})}})},group2:e.group({scope:`hoist`,fields:{power_module:e.string({label:`drone.drone.fields.power_module`,rules:{max:60}}),vtx:e.relation({label:`drone.drone.fields.vtx`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`vtx`}})})}}),group3:e.group({scope:`hoist`,fields:{flight_time:e.string({label:`drone.drone.fields.flight_time`,rules:{max:60}}),firmware:e.string({label:`drone.drone.fields.firmware`,options:`drone-firmware`,strict:!0,noSearch:!0}),firmware_version:e.string({label:`drone.drone.fields.firmware_version`,rules:{max:40}}),firmware_target:e.string({label:`drone.drone.fields.firmware_target`,rules:{max:80}})}}),group4:e.group({scope:`hoist`,fields:{frame_size:e.string({label:`drone.drone.fields.frame_size`,rules:{max:40}}),purpose:e.string({label:`drone.drone.fields.purpose`,rules:{max:200}})}}),group5:e.group({scope:`hoist`,fields:{flight_controller:e.relation({label:`drone.drone.fields.flight_controller`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`flight_controller`}})}),gps_module:e.relation({label:`drone.drone.fields.gps_module`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`gps`}})})}}),group6:e.group({scope:`hoist`,fields:{radio_link:e.string({label:`drone.drone.fields.radio_link`,options:`drone-radio-links`,multiple:!0,strict:!0,noSearch:!0}),receiver:e.string({label:`drone.drone.fields.receiver`,rules:{max:80}}),video_system:e.string({label:`drone.drone.fields.video_system`,options:`drone-video-systems`,strict:!0,noSearch:!0})}})}}),snippets:e.group({scope:`nest`,label:`drone.drone.groups.snippets`,icon:`lucide:terminal`,multiple:!0,fields:{title:e.string({label:`drone.drone.fields.snippet_title`,rules:{max:100}}),summary:e.text({label:`drone.drone.fields.snippet_summary`,rules:{max:500}}),snippet:e.source({label:`drone.drone.fields.snippet`,rules:{ext:`md`}})}}),flights:e.backrefs({label:`drone.drone.fields.flights`,from:{library:`drone`,shelf:`flight`,field:`aircraft`}}),notes:e.text({label:`drone.drone.fields.notes`,rules:{max:2e3}})}}),c=a({id:`drone_battery`,label:`drone.drone_battery.label`,icon:`lucide:battery-full`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`battery`,`rtf`]}},agent:`FPV drone battery characteristics. cells — number of cells (1S/3S/4S). capacity — capacity in mAh. c_rate — discharge current. auw — all-up weight of the assembly in flight.`,fields:{charger:e.string({label:`drone.drone_battery.fields.charger`,rules:{max:100}}),cells:e.string({label:`drone.drone_battery.fields.cells`,options:`drone-cells`,strict:!0,noSearch:!0}),capacity:e.measured({label:`drone.drone_battery.fields.capacity`,units:`energy`}),c_rate:e.string({label:`drone.drone_battery.fields.c_rate`,rules:{max:20}}),auw:e.string({label:`drone.drone_battery.fields.auw`,rules:{max:40}}),flights:e.backrefs({label:`drone.drone_battery.fields.flights`,from:{library:`drone`,shelf:`flight`,field:`batteries`}}),notes:e.text({label:`drone.drone_battery.fields.notes`,rules:{max:2e3}})}}),l=a({id:`drone_vtx`,label:`drone.drone_vtx.label`,icon:`lucide:radio-tower`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`vtx`,`rtf`]}},agent:`FPV video transmitter characteristics. input_voltage — input voltage. protocol — control protocols, codes from the drone-vtx-protocols list. frequency_groups — Betaflight band letters. channel_count — number of channels.`,fields:{input_voltage:e.string({label:`drone.drone_vtx.fields.input_voltage`,rules:{max:40}}),protocol:e.string({label:`drone.drone_vtx.fields.protocol`,options:`drone-vtx-protocols`,multiple:!0,strict:!0,noSearch:!0}),antenna_interface:e.string({label:`drone.drone_vtx.fields.antenna_interface`,options:`drone-rf-connectors`,strict:!0,noSearch:!0}),channel_count:e.int({label:`drone.drone_vtx.fields.channel_count`,rules:{min:0}}),mounting:e.string({label:`drone.drone_vtx.fields.mounting`,options:`drone-mounting`,multiple:!0,strict:!0,noSearch:!0}),built_in_microphone:e.boolean({label:`drone.drone_vtx.fields.built_in_microphone`}),frequency_groups:e.string({label:`drone.drone_vtx.fields.frequency_groups`,options:`drone-bands`,multiple:!0,strict:!0,noSearch:!0}),power_levels:e.keyed({label:`drone.drone_vtx.groups.power_levels`,icon:`lucide:zap`,container:e.row,fields:{level:e.string({label:`drone.drone_vtx.fields.power_level`,options:`drone-vtx-power`,strict:!0,noSearch:!0}),current_ma:e.int({label:`drone.drone_vtx.fields.current_ma`,rules:{min:0}}),dbm:e.real({label:`drone.drone_vtx.fields.dbm`})},by:`level`}),notes:e.text({label:`drone.drone_vtx.fields.notes`,rules:{max:2e3}})}}),u=a({id:`drone_gps`,label:`drone.drone_gps.label`,icon:`lucide:satellite`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`gps`,`rtf`]}},agent:`FPV drone GPS module characteristics. gnss_chip — chipset. compass_chip — magnetometer. satellite_systems — supported satellite systems.`,fields:{gnss_chip:e.string({label:`drone.drone_gps.fields.gnss_chip`,rules:{max:80}}),compass_chip:e.string({label:`drone.drone_gps.fields.compass_chip`,rules:{max:60}}),barometer:e.boolean({label:`drone.drone_gps.fields.barometer`}),interface:e.string({label:`drone.drone_gps.fields.interface`,options:`drone-serial-interfaces`,multiple:!0,strict:!0,noSearch:!0}),input_voltage:e.string({label:`drone.drone_gps.fields.input_voltage`,rules:{max:40}}),update_rate_hz:e.int({label:`drone.drone_gps.fields.update_rate_hz`,rules:{min:0}}),receiving_channels:e.int({label:`drone.drone_gps.fields.receiving_channels`,rules:{min:0}}),supported_protocols:e.string({label:`drone.drone_gps.fields.supported_protocols`,options:`drone-gnss-protocols`,multiple:!0,strict:!0,noSearch:!0}),baud_rates:e.string({label:`drone.drone_gps.fields.baud_rates`,options:`drone-baud-rates`,multiple:!0,strict:!0,noSearch:!0}),satellite_systems:e.string({label:`drone.drone_gps.fields.satellite_systems`,options:`drone-gnss-systems`,multiple:!0,strict:!0,noSearch:!0}),notes:e.text({label:`drone.drone_gps.fields.notes`,rules:{max:2e3}})}}),d=a({id:`drone_flight_controller`,label:`drone.drone_flight_controller.label`,icon:`lucide:sliders-horizontal`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`flight_controller`,`rtf`]}},agent:`FPV drone flight controller characteristics. mcu — processor (STM32F411/F405). gyro — gyroscope. supported_firmware — compatible firmware (Betaflight, INAV).`,fields:{mcu:e.string({label:`drone.drone_flight_controller.fields.mcu`,options:`drone-fc-mcu`,strict:!0,noSearch:!0}),gyro:e.string({label:`drone.drone_flight_controller.fields.gyro`,options:`drone-gyro`,multiple:!0,strict:!0,noSearch:!0}),barometer:e.boolean({label:`drone.drone_flight_controller.fields.barometer`}),osd_chip:e.string({label:`drone.drone_flight_controller.fields.osd_chip`,options:`drone-osd-chip`,strict:!0,noSearch:!0}),blackbox:e.string({label:`drone.drone_flight_controller.fields.blackbox`,options:`drone-blackbox`,strict:!0,noSearch:!0}),bluetooth:e.boolean({label:`drone.drone_flight_controller.fields.bluetooth`}),wifi:e.boolean({label:`drone.drone_flight_controller.fields.wifi`}),current_sensor_input:e.boolean({label:`drone.drone_flight_controller.fields.current_sensor_input`}),power_input:e.string({label:`drone.drone_flight_controller.fields.power_input`,rules:{max:40}}),constant_current:e.string({label:`drone.drone_flight_controller.fields.constant_current`,rules:{max:20}}),peak_current:e.string({label:`drone.drone_flight_controller.fields.peak_current`,rules:{max:20}}),bec_5v:e.string({label:`drone.drone_flight_controller.fields.bec_5v`,rules:{max:20}}),bec_9v:e.string({label:`drone.drone_flight_controller.fields.bec_9v`,rules:{max:20}}),mounting:e.string({label:`drone.drone_flight_controller.fields.mounting`,options:`drone-mounting`,multiple:!0,strict:!0,noSearch:!0}),uart_count:e.int({label:`drone.drone_flight_controller.fields.uart_count`,rules:{min:0}}),supported_firmware:e.string({label:`drone.drone_flight_controller.fields.supported_firmware`,options:`drone-firmware`,multiple:!0,strict:!0,noSearch:!0}),firmware_target:e.string({label:`drone.drone_flight_controller.fields.firmware_target`,rules:{max:80}}),build_role:e.string({label:`drone.drone_flight_controller.fields.build_role`,rules:{max:200}}),notes:e.text({label:`drone.drone_flight_controller.fields.notes`,rules:{max:2e3}})}}),f=a({id:`drone_goggles`,label:`drone.drone_goggles.label`,icon:`lucide:glasses`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:`goggles`},agent:`FPV goggles characteristics. display_size — display diagonal. frequency_bands — supported radio bands. battery_life — runtime on battery.`,fields:{display_size:e.string({label:`drone.drone_goggles.fields.display_size`,rules:{max:20}}),display_resolution:e.string({label:`drone.drone_goggles.fields.display_resolution`,rules:{max:40}}),display_brightness:e.string({label:`drone.drone_goggles.fields.display_brightness`,rules:{max:30}}),view_angle:e.string({label:`drone.drone_goggles.fields.view_angle`,rules:{max:20}}),antenna:e.string({label:`drone.drone_goggles.fields.antenna`,rules:{max:80}}),frequency_bands:e.string({label:`drone.drone_goggles.fields.frequency_bands`,options:`drone-bands`,multiple:!0,strict:!0,noSearch:!0}),battery:e.string({label:`drone.drone_goggles.fields.battery`,rules:{max:60}}),battery_life:e.string({label:`drone.drone_goggles.fields.battery_life`,rules:{max:40}}),charging:e.string({label:`drone.drone_goggles.fields.charging`,rules:{max:60}}),band_channels:e.keyed({label:`drone.drone_goggles.groups.band_channels`,icon:`lucide:radio`,container:e.row,fields:{band:e.string({label:`drone.drone_goggles.fields.band`,options:`drone-bands`,strict:!0,noSearch:!0}),channels:e.int({label:`drone.drone_goggles.fields.channels`,multiple:!0})},by:`band`}),notes:e.text({label:`drone.drone_goggles.fields.notes`,rules:{max:2e3}})}}),p=a({id:`drone_antenna`,label:`drone.drone_antenna.label`,icon:`lucide:radio`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`antenna`,`rtf`]}},agent:`FPV antenna characteristics. rf_band — the bands it covers, codes from drone-rf-bands. polarization — RHCP/LHCP/linear; a video link needs the SAME polarization on both ends. antenna_type — the radiating structure. connector — one model often ships in several connector variants.`,fields:{rf_band:e.string({label:`drone.drone_antenna.fields.rf_band`,options:`drone-rf-bands`,multiple:!0,strict:!0,noSearch:!0}),polarization:e.string({label:`drone.drone_antenna.fields.polarization`,options:`drone-polarization`,strict:!0,noSearch:!0}),antenna_type:e.string({label:`drone.drone_antenna.fields.antenna_type`,options:`drone-antenna-types`,strict:!0,noSearch:!0}),connector:e.string({label:`drone.drone_antenna.fields.connector`,options:`drone-rf-connectors`,multiple:!0,strict:!0,noSearch:!0}),gain_dbi:e.real({label:`drone.drone_antenna.fields.gain_dbi`}),cable_length:e.int({label:`drone.drone_antenna.fields.cable_length`,rules:{min:0}}),notes:e.text({label:`drone.drone_antenna.fields.notes`,rules:{max:2e3}})}}),m=a({id:`drone_receiver`,label:`drone.drone_receiver.label`,icon:`lucide:antenna`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`receiver`,`rtf`]}},agent:`RC receiver characteristics. radio_link — the protocol it binds with (ExpressLRS, Crossfire…). output_protocol — how it talks to the flight controller (CRSF, SBUS…). diversity — two antennas with active switching.`,fields:{radio_link:e.string({label:`drone.drone_receiver.fields.radio_link`,options:`drone-radio-links`,strict:!0,noSearch:!0}),rf_band:e.string({label:`drone.drone_receiver.fields.rf_band`,options:`drone-rf-bands`,multiple:!0,strict:!0,noSearch:!0}),output_protocol:e.string({label:`drone.drone_receiver.fields.output_protocol`,options:`drone-rx-outputs`,multiple:!0,strict:!0,noSearch:!0}),antenna_connector:e.string({label:`drone.drone_receiver.fields.antenna_connector`,options:`drone-rf-connectors`,strict:!0,noSearch:!0}),antenna_count:e.int({label:`drone.drone_receiver.fields.antenna_count`,rules:{min:0}}),telemetry:e.boolean({label:`drone.drone_receiver.fields.telemetry`}),diversity:e.boolean({label:`drone.drone_receiver.fields.diversity`}),input_voltage:e.string({label:`drone.drone_receiver.fields.input_voltage`,rules:{max:40}}),firmware_version:e.string({label:`drone.drone_receiver.fields.firmware_version`,rules:{max:40}}),notes:e.text({label:`drone.drone_receiver.fields.notes`,rules:{max:2e3}})}}),h=a({id:`drone_camera`,label:`drone.drone_camera.label`,icon:`lucide:camera`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{type:`drone`,subtype:{$in:[`camera`,`rtf`]}},agent:`FPV camera characteristics. sensor — the sensor model (free text, e.g. Sony Super HAD II). resolution_tvl — analog horizontal resolution in TVL. aspect_ratio — 4:3 / 16:9 / switchable. output — the video signal it produces (analog CVBS or a digital HD system).`,fields:{sensor:e.string({label:`drone.drone_camera.fields.sensor`,rules:{max:100}}),resolution_tvl:e.int({label:`drone.drone_camera.fields.resolution_tvl`,rules:{min:0}}),aspect_ratio:e.string({label:`drone.drone_camera.fields.aspect_ratio`,options:`drone-camera-aspect`,strict:!0,noSearch:!0}),lens_mm:e.real({label:`drone.drone_camera.fields.lens_mm`}),fov_deg:e.int({label:`drone.drone_camera.fields.fov_deg`,rules:{min:0}}),output:e.string({label:`drone.drone_camera.fields.output`,options:`drone-camera-output`,strict:!0,noSearch:!0}),camera_size:e.string({label:`drone.drone_camera.fields.camera_size`,options:`drone-camera-sizes`,strict:!0,noSearch:!0}),input_voltage:e.string({label:`drone.drone_camera.fields.input_voltage`,rules:{max:40}}),notes:e.text({label:`drone.drone_camera.fields.notes`,rules:{max:2e3}})}}),g=[`ok`,`low_voltage`,`crash`,`lost`],_=[{value:`ok`,title:`drone.options.outcome.ok`,tone:`success`},{value:`low_voltage`,title:`drone.options.outcome.low_voltage`,tone:`warning`},{value:`crash`,title:`drone.options.outcome.crash`,tone:`danger`},{value:`lost`,title:`drone.options.outcome.lost`,tone:`danger`}],v=e=>Array.isArray(e)?e.filter(e=>e&&typeof e==`object`):[];function y(e,t){let n=[];for(let r of v(e)){let e=r[t];if(e==null||e===``)continue;let i=Number(e);Number.isFinite(i)&&(n.includes(i)||n.push(i))}return n}function b(e,t=`outcome`){let n=-1;for(let r of v(e)){let e=g.indexOf(r[t]);e>n&&(n=e)}return n<0?null:g[n]}var x=n({shelf:`flight`,library:`drone`,label:`drone.flight.label`,icon:`lucide:plane-takeoff`,agent:"A flying session, not a single sortie: one record is one outing — date, place, aircraft — and each battery pack flown is a row of `packs` (battery, duration in seconds, outcome, notes). `batteries` and `outcome` are SERVER-OWNED derivations over those rows and are rejected if sent: `batteries` indexes the distinct batteries used, `outcome` is the worst row outcome. Record a crash by setting that pack's outcome and listing the broken parts in `damage`, not by prose in `notes`. The `aircraft` picker only offers things/item[subtype='aircraft'] — a ready-to-fly kit (subtype='rtf') cannot be selected there today, so log its flights against an 'aircraft'-subtype record instead.",views:{title:`date`,listKind:`map`,list:[`aircraft`,`place`,`outcome`],inline:[`date`,`aircraft`]},fields:{date:e.date({label:`drone.flight.fields.date`,rules:{min:`2000-01-01`,max:`today`},ui:{span:4}}),description:e.text({label:`drone.flight.fields.description`,rules:{max:1e3}}),place:e.geo({label:`drone.flight.fields.place`}),aircraft:e.relation({label:`drone.flight.fields.aircraft`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`aircraft`}})}),batteries:e.relation({label:`drone.flight.fields.batteries`,multiple:!0,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`battery`}}),value:({record:e})=>y(e.packs,`battery`)}),weather:e.group({scope:`hoist`,label:`drone.flight.groups.weather`,icon:`lucide:cloud-sun`,fields:{temp:e.measured({label:`drone.flight.fields.temp`,units:`temperature`,ui:{span:4}}),wind:e.measured({label:`drone.flight.fields.wind`,units:`speed`,ui:{span:4}}),sky:e.string({label:`drone.flight.fields.sky`,options:`drone-sky`,strict:!0,noSearch:!0})}}),packs:e.row({scope:`nest`,multiple:!0,label:`drone.flight.fields.packs`,icon:`lucide:battery-charging`,fields:{battery:e.relation({label:`drone.flight.fields.battery`,options:t({library:`things`,shelf:`item`,filter:{type:`drone`,subtype:`battery`}}),mutate:[`batteries`]}),duration:e.duration({label:`drone.flight.fields.duration`}),outcome:e.string({label:`drone.flight.fields.pack_outcome`,options:`drone-outcomes`,strict:!0,noSearch:!0,mutate:[`outcome`]}),notes:e.text({label:`drone.flight.fields.pack_notes`,rules:{max:500}})}}),outcome:e.string({label:`drone.flight.fields.outcome`,options:`drone-outcomes`,strict:!0,noSearch:!0,value:({record:e})=>b(e.packs)}),setup:e.group({scope:`hoist`,label:`drone.flight.groups.setup`,icon:`lucide:sliders-horizontal`,fields:{firmware_version:e.string({label:`drone.flight.fields.firmware_version`,rules:{max:40}}),tune:e.text({label:`drone.flight.fields.tune`,rules:{max:2e3}})}}),damage:e.relation({label:`drone.flight.fields.damage`,multiple:!0,options:t({library:`things`,shelf:`item`,filter:{type:`drone`}})}),video:e.video({label:`drone.flight.fields.video`,multiple:!0}),photos:e.image({label:`drone.flight.fields.photos`,multiple:!0}),edit_link:e.link({label:`drone.flight.fields.edit_link`}),tags:e.tags({label:`drone.flight.fields.tags`}),notes:e.text({label:`drone.flight.fields.notes`,rules:{max:2e3}})}}),S=i({id:`drone`,version:`1.0.0`,dependsOn:[`things`,`geo`],label:`drone.plugin.label`,description:`drone.plugin.description`,libraries:[{meta:r({id:`drone`,label:`drone.library.label`,icon:`tb:drone`,agent:`FPV drones and their components. A component is a things/item row with type=drone — this library owns no table for those. A FLIGHT is different: it is an event, not a thing, and it is this library's one table (flight): one record per outing, with the battery packs flown as rows inside it.`}),shelves:[x]}],extends_:[s,c,l,u,d,f,p,m,h],showcases:[o({id:`fleet`,library:`drone`,label:`drone.fleet.label`,icon:`lucide:plane`,source:{library:`things`,shelf:`item`},filter:{type:`drone`},columns:[`subtype`,`brand`,`model`,`location`,`condition`],defaultGroupBy:`subtype`,createDefaults:{type:`drone`}})],optionLists:[{name:`drone-bands`,options:[{value:`A`,title:`A`},{value:`B`,title:`B`},{value:`E`,title:`E`},{value:`F`,title:`F`},{value:`R`,title:`R`},{value:`L`,title:`L`},{value:`U`,title:`U`},{value:`O`,title:`O`},{value:`H`,title:`H`}]},{name:`drone-vtx-power`,options:[{value:`pit`,title:`PIT`},{value:`25mw`,title:`25 mW`},{value:`100mw`,title:`100 mW`},{value:`200mw`,title:`200 mW`},{value:`350mw`,title:`350 mW`},{value:`400mw`,title:`400 mW`},{value:`600mw`,title:`600 mW`},{value:`800mw`,title:`800 mW`},{value:`1000mw`,title:`1 W`},{value:`1600mw`,title:`1.6 W`},{value:`2500mw`,title:`2.5 W`}]},{name:`drone-vtx-protocols`,options:[{value:`smartaudio_1_0`,title:`SmartAudio 1.0`},{value:`smartaudio_2_0`,title:`SmartAudio 2.0`},{value:`smartaudio_2_1`,title:`SmartAudio 2.1`},{value:`tramp`,title:`IRC Tramp`},{value:`msp_displayport`,title:`MSP DisplayPort`},{value:`none`,title:`drone.options.none`}]},{name:`drone-rf-connectors`,options:[{value:`ipex_mhf1`,title:`IPEX / MHF1 (U.FL)`},{value:`ipex_mhf3`,title:`IPEX MHF3`},{value:`mmcx`,title:`MMCX`},{value:`sma`,title:`SMA`},{value:`rp_sma`,title:`RP-SMA`},{value:`ufl_solder`,title:`U.FL (soldered)`}]},{name:`drone-mounting`,options:[{value:`16x16_m2`,title:`16×16 mm M2`},{value:`20x20_m2`,title:`20×20 mm M2`},{value:`20x20_m3`,title:`20×20 mm M3`},{value:`25.5x25.5_m2`,title:`25.5×25.5 mm M2`},{value:`30.5x30.5_m3`,title:`30.5×30.5 mm M3`},{value:`adhesive`,title:`drone.options.adhesive`}]},{name:`drone-firmware`,options:[{value:`betaflight`,title:`Betaflight`},{value:`inav`,title:`INAV`},{value:`ardupilot`,title:`ArduPilot`},{value:`emuflight`,title:`EmuFlight`},{value:`rotorflight`,title:`Rotorflight`},{value:`kiss`,title:`KISS`},{value:`cleanflight`,title:`Cleanflight`}]},{name:`drone-fc-mcu`,options:[{value:`stm32f411`,title:`STM32F411`},{value:`stm32f405`,title:`STM32F405`},{value:`stm32f722`,title:`STM32F722`},{value:`stm32f745`,title:`STM32F745`},{value:`stm32f765`,title:`STM32F765`},{value:`stm32h743`,title:`STM32H743`},{value:`stm32h750`,title:`STM32H750`},{value:`at32f435`,title:`AT32F435`},{value:`gd32f405`,title:`GD32F405`}]},{name:`drone-gyro`,options:[{value:`mpu6000`,title:`MPU6000`},{value:`mpu6500`,title:`MPU6500`},{value:`icm20602`,title:`ICM20602`},{value:`icm20689`,title:`ICM20689`},{value:`icm42688p`,title:`ICM42688-P`},{value:`icm42605`,title:`ICM42605`},{value:`bmi270`,title:`BMI270`},{value:`bmi160`,title:`BMI160`}]},{name:`drone-osd-chip`,options:[{value:`at7456e`,title:`AT7456E`},{value:`max7456`,title:`MAX7456`},{value:`msp_displayport`,title:`MSP DisplayPort`},{value:`none`,title:`drone.options.none`}]},{name:`drone-blackbox`,options:[{value:`none`,title:`drone.options.none`},{value:`flash_8mb`,title:`Flash 8 MB`},{value:`flash_16mb`,title:`Flash 16 MB`},{value:`flash_32mb`,title:`Flash 32 MB`},{value:`sd_card`,title:`microSD`}]},{name:`drone-gnss-systems`,options:[{value:`gps`,title:`GPS`},{value:`glonass`,title:`GLONASS`},{value:`galileo`,title:`Galileo`},{value:`beidou`,title:`BeiDou`},{value:`qzss`,title:`QZSS`},{value:`sbas`,title:`SBAS`},{value:`navic`,title:`NavIC`}]},{name:`drone-gnss-protocols`,options:[{value:`ubx`,title:`UBX`},{value:`nmea`,title:`NMEA`},{value:`rtcm3`,title:`RTCM3`},{value:`msp`,title:`MSP`}]},{name:`drone-baud-rates`,options:[{value:`4800`,title:`4800`},{value:`9600`,title:`9600`},{value:`19200`,title:`19200`},{value:`38400`,title:`38400`},{value:`57600`,title:`57600`},{value:`115200`,title:`115200`},{value:`230400`,title:`230400`},{value:`460800`,title:`460800`},{value:`921600`,title:`921600`}]},{name:`drone-serial-interfaces`,options:[{value:`uart`,title:`UART`},{value:`i2c`,title:`I2C`},{value:`spi`,title:`SPI`},{value:`can`,title:`CAN`}]},{name:`drone-video-systems`,options:[{value:`analog_5_8`,title:`drone.options.videoSystems.analog_5_8`},{value:`dji_v1_v2`,title:`DJI V1/V2`},{value:`dji_o3`,title:`DJI O3`},{value:`dji_o4`,title:`DJI O4`},{value:`walksnail_avatar`,title:`Walksnail Avatar`},{value:`hdzero`,title:`HDZero`}]},{name:`drone-radio-links`,options:[{value:`elrs_2_4`,title:`ExpressLRS 2.4 GHz`},{value:`elrs_900`,title:`ExpressLRS 868/915 MHz`},{value:`crossfire`,title:`TBS Crossfire`},{value:`tracer`,title:`TBS Tracer`},{value:`ghost`,title:`ImmersionRC Ghost`},{value:`frsky_d16`,title:`FrSky D16`},{value:`frsky_d8`,title:`FrSky D8`},{value:`dsmx`,title:`Spektrum DSMX`},{value:`dji`,title:`DJI`}]},{name:`drone-rf-bands`,options:[{value:`5_8ghz`,title:`5.8 GHz`},{value:`2_4ghz`,title:`2.4 GHz`},{value:`1_2ghz`,title:`1.2 GHz`},{value:`900mhz`,title:`868/915 MHz`},{value:`433mhz`,title:`433 MHz`}]},{name:`drone-polarization`,options:[{value:`rhcp`,title:`drone.options.polarization.rhcp`},{value:`lhcp`,title:`drone.options.polarization.lhcp`},{value:`linear`,title:`drone.options.polarization.linear`}]},{name:`drone-antenna-types`,options:[{value:`omni`,title:`drone.options.antennaTypes.omni`},{value:`patch`,title:`drone.options.antennaTypes.patch`},{value:`helical`,title:`drone.options.antennaTypes.helical`},{value:`pagoda`,title:`drone.options.antennaTypes.pagoda`},{value:`cloverleaf`,title:`drone.options.antennaTypes.cloverleaf`},{value:`monopole`,title:`drone.options.antennaTypes.monopole`},{value:`whip`,title:`drone.options.antennaTypes.whip`}]},{name:`drone-cells`,options:[{value:`1s`,title:`1S`},{value:`2s`,title:`2S`},{value:`3s`,title:`3S`},{value:`4s`,title:`4S`},{value:`5s`,title:`5S`},{value:`6s`,title:`6S`},{value:`7s`,title:`7S`},{value:`8s`,title:`8S`},{value:`12s`,title:`12S`}]},{name:`drone-rx-outputs`,options:[{value:`crsf`,title:`CRSF`},{value:`sbus`,title:`SBUS`},{value:`ibus`,title:`IBUS`},{value:`ppm`,title:`PPM`},{value:`pwm`,title:`PWM`},{value:`spektrum`,title:`Spektrum`},{value:`ghst`,title:`GHST`}]},{name:`drone-camera-aspect`,options:[{value:`4_3`,title:`4:3`},{value:`16_9`,title:`16:9`},{value:`switchable`,title:`drone.options.cameraAspect.switchable`}]},{name:`drone-camera-output`,options:[{value:`analog_cvbs`,title:`drone.options.cameraOutput.analog_cvbs`},{value:`dji`,title:`DJI`},{value:`walksnail`,title:`Walksnail`},{value:`hdzero`,title:`HDZero`}]},{name:`drone-camera-sizes`,options:[{value:`nano`,title:`Nano`},{value:`micro`,title:`Micro`},{value:`mini`,title:`Mini`},{value:`full`,title:`Full-size`},{value:`whoop`,title:`Whoop`}]},{name:`drone-outcomes`,options:[..._]},{name:`drone-sky`,options:[{value:`clear`,title:`drone.options.sky.clear`},{value:`cloudy`,title:`drone.options.sky.cloudy`},{value:`overcast`,title:`drone.options.sky.overcast`},{value:`fog`,title:`drone.options.sky.fog`},{value:`rain`,title:`drone.options.sky.rain`},{value:`snow`,title:`drone.options.sky.snow`}]}],fieldContribs:[{library:`things`,shelf:`item`,field:`type`,options:[{value:`drone`,title:`drone.drone.label`}]},{library:`things`,shelf:`item`,field:`subtype`,options:[{value:`aircraft`,title:`drone.contrib.subtype.aircraft`,when:{type:`drone`}},{value:`battery`,title:`drone.drone_battery.label`,when:{type:`drone`}},{value:`vtx`,title:`drone.drone_vtx.label`,when:{type:`drone`}},{value:`gps`,title:`drone.drone_gps.label`,when:{type:`drone`}},{value:`flight_controller`,title:`drone.drone_flight_controller.label`,when:{type:`drone`}},{value:`goggles`,title:`drone.drone_goggles.label`,when:{type:`drone`}},{value:`radio`,title:`drone.contrib.subtype.radio`,when:{type:`drone`}},{value:`camera`,title:`drone.drone_camera.label`,when:{type:`drone`}},{value:`antenna`,title:`drone.drone_antenna.label`,when:{type:`drone`}},{value:`receiver`,title:`drone.drone_receiver.label`,when:{type:`drone`}},{value:`frame`,title:`drone.contrib.subtype.frame`,when:{type:`drone`}},{value:`rtf`,title:`drone.contrib.subtype.rtf`,when:{type:`drone`}},{value:`accessory`,title:`drone.contrib.subtype.accessory`,when:{type:`drone`}}]}]});export{S as default};
@@ -1,4 +1,4 @@
1
- import{D as e,R as t,T as n,j as r,k as i,n as a,r as o}from"./fields-CV3RQg0Y.js";import{a as s}from"./shelf-Cj_pNvd-.js";import{i as c,n as l}from"./plugin-Cjr7lgQH.js";import{t as u}from"./extend-yQ8zoqGc.js";import{t as d}from"./settings-Bo5IOwVg.js";var f=/^[A-Za-z]{2}\d{2}[A-Za-z0-9]{11,30}$/;function p(e){let t=e.toUpperCase().replace(/\s+/g,``),n=t.slice(4)+t.slice(0,4),r=``;for(let e of n){let t=e.charCodeAt(0);t>=65&&t<=90?r+=(t-55).toString():r+=e}let i=0;for(let e of r)i=(i*10+(e.charCodeAt(0)-48))%97;return i===1}function m(a){let o=t().regex(f,{message:r(`pattern`,{messageKey:`core.presets.iban`})}).refine(p,{message:r(`pattern`,{messageKey:`core.presets.iban`})});return e(void 0,a,n({kind:`text`,label:a.label??``,prim:`text`,column:`text`,hints:{mask:`iban`,maskStore:`unmasked`},zod:i(o)},a.multiple??!1))}var h=/^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$/;function g(a){let o=t().regex(h,{message:r(`pattern`,{messageKey:`finance.presets.bic`})});return e(void 0,a,n({kind:`text`,label:a.label??``,prim:`text`,column:`text`,hints:{},zod:i(o)},a.multiple??!1))}var _=s({shelf:`account`,library:`finance`,label:`finance.account.label`,icon:`lucide:landmark`,agent:`Firefly III account (read-only mirror). kind — account type.
1
+ import{D as e,R as t,T as n,j as r,k as i,n as a,r as o}from"./fields-Ce51pRua.js";import{a as s}from"./shelf-DjiUBfgQ.js";import{i as c,n as l}from"./plugin-Cjr7lgQH.js";import{t as u}from"./extend-CHOe1AVl.js";import{t as d}from"./settings-BEzSaRjz.js";var f=/^[A-Za-z]{2}\d{2}[A-Za-z0-9]{11,30}$/;function p(e){let t=e.toUpperCase().replace(/\s+/g,``),n=t.slice(4)+t.slice(0,4),r=``;for(let e of n){let t=e.charCodeAt(0);t>=65&&t<=90?r+=(t-55).toString():r+=e}let i=0;for(let e of r)i=(i*10+(e.charCodeAt(0)-48))%97;return i===1}function m(a){let o=t().regex(f,{message:r(`pattern`,{messageKey:`core.presets.iban`})}).refine(p,{message:r(`pattern`,{messageKey:`core.presets.iban`})});return e(void 0,a,n({kind:`text`,label:a.label??``,prim:`text`,column:`text`,hints:{mask:`iban`,maskStore:`unmasked`},zod:i(o)},a.multiple??!1))}var h=/^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$/;function g(a){let o=t().regex(h,{message:r(`pattern`,{messageKey:`finance.presets.bic`})});return e(void 0,a,n({kind:`text`,label:a.label??``,prim:`text`,column:`text`,hints:{},zod:i(o)},a.multiple??!1))}var _=s({shelf:`account`,library:`finance`,label:`finance.account.label`,icon:`lucide:landmark`,agent:`Firefly III account (read-only mirror). kind — account type.
2
2
  current_balance — current balance. firefly_id — external key (do not edit).`,views:{list:[`kind`,`currency`,`current_balance`]},fields:{name:a.title({label:`core.fields.name`}),description:a.text({label:`finance.account.fields.description`,rules:{max:1e3}}),balance:a.balance({source:{current_balance:a.money({label:`finance.account.fields.current_balance`})}}),status:a.status({source:{kind:a.string({label:`finance.account.fields.kind`,strict:!0,noSearch:!0,options:[{value:`asset`,title:`finance.account.options.asset`},{value:`expense`,title:`finance.account.options.expense`},{value:`revenue`,title:`finance.account.options.revenue`},{value:`liability`,title:`finance.account.options.liability`},{value:`cash`,title:`finance.account.options.cash`}]})}}),sheet:a.sheet({fields:{account:{currency:a.currency({label:`finance.account.fields.currency`}),iban:m({label:`finance.account.fields.iban`})},bank:{bank:a.string({label:`finance.account.fields.bank`,rules:{max:120}}),bic:g({label:`finance.account.fields.bic`})}}}),firefly_id:a.string({label:`finance.account.fields.firefly_id`,rules:{max:32}}),notes:a.text({label:`finance.account.fields.notes`,rules:{max:2e3}})}}),v=s({shelf:`transaction`,library:`finance`,label:`finance.transaction.label`,icon:`lucide:arrow-left-right`,agent:`Firefly III transaction (read-only). Each split = a separate record.
3
3
  source/destination — accounts. firefly_id — split journal id (do not edit).`,views:{list:[`date`,`amount`,`kind`]},fields:{description:a.title({label:`finance.transaction.fields.description`}),flow:a.flow({amount:{amount:a.money({label:`finance.transaction.fields.amount`})},from:{source:a.relation({label:`finance.transaction.fields.source`,options:o({library:`finance`,shelf:`account`})})},to:{destination:a.relation({label:`finance.transaction.fields.destination`,options:o({library:`finance`,shelf:`account`})})},meta:{date:a.date({label:`finance.transaction.fields.date`,ui:{span:3}}),kind:a.string({label:`finance.transaction.fields.kind`,strict:!0,noSearch:!0,ui:{span:3},options:[{value:`withdrawal`,title:`finance.transaction.options.withdrawal`},{value:`deposit`,title:`finance.transaction.options.deposit`,tone:`success`},{value:`transfer`,title:`finance.transaction.options.transfer`}]}),category:a.string({label:`finance.transaction.fields.category`,rules:{max:100},ui:{span:3}}),currency:a.currency({label:`core.fields.currency`,ui:{span:3}})}}),firefly_id:a.string({label:`finance.transaction.fields.firefly_id`,rules:{max:32}}),notes:a.text({label:`finance.transaction.fields.notes`,rules:{max:2e3}})}}),y=s({shelf:`bill`,library:`finance`,label:`finance.bill.label`,icon:`lucide:receipt`,agent:`Recurring Firefly III payment (Bill = subscription, read-only).
4
4
  repeat — recurrence. next_expected — next expected date. firefly_id — do not edit.`,views:{list:[`amount_min`,`repeat`,`next_expected`,`active`]},fields:{name:a.title({label:`core.fields.name`}),description:a.text({label:`finance.bill.fields.description`,rules:{max:1e3}}),currency:a.currency({label:`core.fields.currency`}),sheet:a.sheet({fields:{amount:{amount_min:a.money({label:`finance.bill.fields.amount_min`}),amount_max:a.money({label:`finance.bill.fields.amount_max`})},schedule:{repeat:a.string({label:`finance.bill.fields.repeat`,strict:!0,noSearch:!0,options:[{value:`weekly`,title:`finance.bill.options.weekly`},{value:`monthly`,title:`finance.bill.options.monthly`},{value:`quarterly`,title:`finance.bill.options.quarterly`},{value:`yearly`,title:`finance.bill.options.yearly`}]})}}}),countdown:a.countdown({source:{next_expected:a.date({label:`finance.bill.fields.next_expected`})},caption:`units.days`}),active:a.boolean({label:`finance.bill.fields.active`}),firefly_id:a.string({label:`finance.bill.fields.firefly_id`,rules:{max:32}}),notes:a.text({label:`finance.bill.fields.notes`,rules:{max:2e3}})}}),b=e=>typeof e==`number`&&Number.isFinite(e)?e:Number.isFinite(Number(e))&&e!==null&&e!==``?Number(e):null,x=u({id:`item_financing`,label:`finance.item_financing.label`,icon:`lucide:credit-card`,attachTo:[{library:`things`,shelf:`item`}],showWhen:{paymentStatus:{$in:[`installment`,`credit`]}},agent:`Installment/credit details for an item. creditor — who is owed (bank/store).
@@ -0,0 +1 @@
1
+ import{i as e,r as t,s as n}from"./data-size-CO-LGHbN.js";import{a as r,c as i,i as a,n as o,o as s,r as c,s as l,t as u}from"./src-C06O0ceD.js";export{c as SCHEME_TO_ACCESS_TYPE,a as cidr,t as dataSize,o as default,u as dev,e as diskSize,r as hostname,s as imei,l as ip,i as mac,n as ram};
@@ -1 +1 @@
1
- import{n as e,r as t}from"./fields-CV3RQg0Y.js";import{a as n}from"./shelf-Cj_pNvd-.js";import{i as r,n as i}from"./plugin-Cjr7lgQH.js";var a=(e,t)=>(e??[]).reduce((e,n)=>{let r=n?.[t];return e+(Number(r&&typeof r==`object`?r.value:r)||0)},0),o=e=>e&&typeof e==`object`?e.unit??null:null,s=()=>e.string({options:`cooking`,value:({record:e})=>o(e.quantity),strict:!0}),c=(e,t)=>(e??[]).map(e=>e?.[t]==null?``:String(e[t])).filter(e=>e!==``).sort()[0]??null,l=e=>{let t=e?.value;return typeof t==`number`&&Number.isFinite(t)?t:null},u=n({shelf:`food_item`,library:`kitchen`,label:`kitchen.food_item.label`,icon:`lucide:soup`,agent:'A kitchen product is generic (buckwheat, milk), and its `variants` rows are the actual goods on the shelf. The unit is declared once on the product, inside its stock: `quantity` is written as `{"unit": "<unit>"}` — the unit alone, never a value. Every amount below it — `minQuantity`, each variant row\'s `quantity` — is written as `{"value": <number>}` alone, on that scale. Do NOT send a unit inside those amounts: the server fills it in from the product\'s `quantity.unit` and discards anything you put there. Reads hand them back as `{"value": …, "unit": …}`, which you may echo unchanged. The `value` of the product\'s `quantity`, and `expires`, are computed from the variants and MUST NOT be written — to record a purchase or a write-off, change the `quantity` of the relevant variant row, or add a variant row for a good that is not there yet. A variant with quantity 0 means "this good is known, none in stock" and is a shopping-list candidate, so do not delete it.',views:{list:[`subcategory`,`quantity`,`expires`]},fields:{name:e.title({label:`core.fields.name`}),stock:e.stats({fields:{quantity:e.measured({label:`kitchen.food_item.fields.quantity`,units:`cooking`,rules:{min:0},fields:{value:e.real({value:({record:e})=>a(e.variants,`quantity`),mutate:[`stockState`]}),unit:e.string({options:`cooking`,strict:!0,mutate:[`minQuantity.unit`,`variants.quantity.unit`]})}}),status:e.status({source:{stockState:e.string({label:`kitchen.food_item.fields.stockState`,value:({record:e})=>{let t=l(e.minQuantity);return t==null?`ok`:(l(e.quantity)??0)<t?`low`:`ok`},strict:!0,noSearch:!0,options:[{value:`ok`,title:`kitchen.food_item.options.stockState.ok`,tone:`success`},{value:`low`,title:`kitchen.food_item.options.stockState.low`,tone:`danger`}]})}}),minQuantity:e.measured({label:`kitchen.food_item.fields.minQuantity`,units:`cooking`,rules:{min:0},fields:{unit:s(),value:e.real({rules:{min:0},mutate:[`stockState`]})}}),expires:e.reminder({label:`kitchen.food_item.fields.expires`,rules:{lead:14},value:({record:e})=>c(e.variants,`expires`)})}}),hairline:e.divider({}),about:e.illustrated({label:`kitchen.food_item.fields.about`,fields:{image:e.avatar({}),text:e.text({rules:{max:1e3}})}}),photos:e.image({label:`kitchen.food_item.fields.photos`,multiple:!0}),variants:e.row({scope:`nest`,multiple:!0,label:`kitchen.food_item.fields.variants`,icon:`lucide:package`,fields:{name:e.string({label:`kitchen.food_item.variant.name`,rules:{max:200}}),quantity:e.measured({label:`kitchen.food_item.variant.quantity`,units:`cooking`,rules:{min:0},fields:{unit:s(),value:e.real({rules:{min:0},mutate:[`quantity.value`]})}}),expires:e.reminder({label:`kitchen.food_item.variant.expires`,rules:{lead:14},mutate:[`expires`]}),location:e.relation({label:`kitchen.food_item.variant.location`,options:t({library:`things`,shelf:`storage_location`})}),shops:e.link({label:`kitchen.food_item.variant.shops`,multiple:!0}),photo:e.image({label:`kitchen.food_item.variant.photo`})}}),subcategory:e.string({label:`kitchen.food_item.fields.subcategory`,rules:{max:100}}),tags:e.tags({label:`kitchen.food_item.fields.tags`}),notes:e.text({label:`kitchen.food_item.fields.notes`,rules:{max:2e3}})}}),d=async({ref:e})=>{let t=(await e?.(`product`))?.quantity;return t&&typeof t==`object`?t.unit??null:null},f=e=>{let t=e?.value;return typeof t==`number`&&Number.isFinite(t)?t:null},p=async({ref:e})=>(await e?.(`product`))?.quantity??null,m=n({shelf:`food_recipe`,library:`kitchen`,label:`kitchen.food_recipe.label`,icon:`lucide:clipboard-list`,views:{list:[`category`,`description`,`prep_time`,`cook_time`]},fields:{name:e.title({label:`core.fields.name`}),cooking:e.stats({fields:{status:e.status({source:{readiness:e.string({label:`kitchen.food_recipe.fields.readiness`,value:({record:e})=>(e.ingredients??[]).filter(e=>!e.optional).every(e=>e.stock_state===`enough`)?`ready`:`not_ready`,strict:!0,noSearch:!0,options:[{value:`ready`,title:`kitchen.food_recipe.options.readiness.ready`,tone:`success`},{value:`not_ready`,title:`kitchen.food_recipe.options.readiness.not_ready`,tone:`danger`}]})}}),servings:e.int({label:`kitchen.food_recipe.fields.servings`,rules:{min:1,max:100}}),prep_time:e.duration({label:`kitchen.food_recipe.fields.prep_time`}),cook_time:e.duration({label:`kitchen.food_recipe.fields.cook_time`})}}),hairline:e.divider({}),description:e.text({label:`kitchen.food_recipe.fields.description`,rules:{max:500}}),images:e.image({label:`kitchen.food_recipe.fields.images`,multiple:!0}),ingredients:e.row({scope:`nest`,multiple:!0,label:`kitchen.food_recipe.fields.ingredients`,icon:`lucide:carrot`,rules:{unique:[`product`]},fields:{product:e.relation({label:`kitchen.food_recipe.ingredient.product`,options:t({library:`kitchen`,shelf:`food_item`})}),amount:e.measured({label:`kitchen.food_recipe.ingredient.amount`,units:`cooking`,rules:{min:0},fields:{unit:e.string({options:`cooking`,value:d,strict:!0,cache:0}),value:e.real({rules:{min:0},mutate:[`.stock_state`]})}}),optional:e.boolean({label:`kitchen.food_recipe.ingredient.optional`,mutate:[`readiness`]}),stock:e.measured({label:`kitchen.food_recipe.ingredient.stock`,units:`cooking`,cache:0,value:p}),stock_state:e.string({label:`kitchen.food_recipe.ingredient.stock_state`,cache:0,value:async e=>{let t=f(await p(e));if(t==null)return null;let n=f(e.parent?.amount);return n==null?t>0?null:`missing`:t>=n?`enough`:t>0?`partial`:`missing`},mutate:[`readiness`],strict:!0,noSearch:!0,options:[{value:`enough`,title:`kitchen.food_recipe.options.stock_state.enough`,icon:{kind:`icon`,value:`lucide:check`},tone:`success`},{value:`partial`,title:`kitchen.food_recipe.options.stock_state.partial`,icon:{kind:`icon`,value:`lucide:minus`},tone:`danger`},{value:`missing`,title:`kitchen.food_recipe.options.stock_state.missing`,icon:{kind:`icon`,value:`lucide:x`},tone:`danger`}]})}}),ingredients_free:e.row({scope:`nest`,multiple:!0,label:`kitchen.food_recipe.fields.ingredients_free`,icon:`lucide:list`,rules:{unique:[`product`]},fields:{product:e.string({label:`kitchen.food_recipe.ingredient_free.product`,rules:{max:200}}),unit:e.unit({label:`kitchen.food_recipe.ingredient_free.unit`,options:`cooking`}),amount:e.amount({label:`kitchen.food_recipe.ingredient_free.amount`,unitFrom:`unit`,rules:{min:0}}),optional:e.boolean({label:`kitchen.food_recipe.ingredient_free.optional`})}}),prose:e.prose({label:`kitchen.food_recipe.fields.steps`,icon:`lucide:chef-hat`,fields:{steps:e.markdown({label:`kitchen.food_recipe.fields.steps_body`,rules:{max:5e3}})}}),properties:e.properties({columns:2,fields:{category:e.string({label:`kitchen.food_recipe.fields.category`,multiple:!0,strict:!0,noSearch:!0,ui:{span:6},options:[{value:`first`,title:`kitchen.food_recipe.options.category.first`},{value:`main`,title:`kitchen.food_recipe.options.category.main`},{value:`salad`,title:`kitchen.food_recipe.options.category.salad`},{value:`appetizer`,title:`kitchen.food_recipe.options.category.appetizer`},{value:`side`,title:`kitchen.food_recipe.options.category.side`},{value:`dessert`,title:`kitchen.food_recipe.options.category.dessert`},{value:`drink`,title:`kitchen.food_recipe.options.category.drink`},{value:`sauce`,title:`kitchen.food_recipe.options.category.sauce`}]}),difficulty:e.string({label:`kitchen.food_recipe.fields.difficulty`,strict:!0,noSearch:!0,ui:{span:6},options:[{value:`easy`,title:`kitchen.food_recipe.options.difficulty.easy`},{value:`medium`,title:`kitchen.food_recipe.options.difficulty.medium`},{value:`hard`,title:`kitchen.food_recipe.options.difficulty.hard`}]})}}),tags:e.tags({label:`kitchen.food_recipe.fields.tags`}),notes:e.text({label:`kitchen.food_recipe.fields.notes`,rules:{max:1e3}})}}),h=n({shelf:`preferences`,library:`kitchen`,label:`kitchen.preferences.label`,icon:`lucide:notebook-pen`,single:!0,agent:`One record. The household food habits, diets and allergies; where groceries are bought, what is bought there and in what volumes; which kitchen appliances exist and which do not. Read it before suggesting recipes, building a shopping list, or planning a menu. An appliance listed as absent is a fact, not a gap — do not propose recipes that need it.`,fields:{preferences:e.markdown({label:`kitchen.preferences.fields.preferences`,rules:{max:1e4}}),shops:e.markdown({label:`kitchen.preferences.fields.shops`,rules:{max:1e4}}),equipment:e.markdown({label:`kitchen.preferences.fields.equipment`,rules:{max:1e4}}),notes:e.text({label:`kitchen.preferences.fields.notes`,rules:{max:1e4}})}}),g=i({id:`kitchen`,version:`1.0.0`,dependsOn:[`things`],label:`kitchen.plugin.label`,description:`kitchen.plugin.description`,libraries:[{meta:r({id:`kitchen`,label:`kitchen.library.label`,icon:`lucide:cooking-pot`,agent:{description:`Food inventory and recipes — what is in stock, what is expiring, what can be cooked.`,instructions:`Read kitchen/preferences before creating, merging or renaming a product: it records how this household splits products from variants, which units each family of goods uses, and why. It governs — these rules are the mechanics, that record is the intent.`},starterHint:`what's expiring soon, or what can be cooked from what's in stock`}),shelves:[u,m,h]}],fieldContribs:[{library:`things`,shelf:`item`,field:`type`,options:[{value:`kitchenware`,title:`kitchen.contrib.type.kitchenware`}]}]});export{g as default};
1
+ import{n as e,r as t}from"./fields-Ce51pRua.js";import{a as n}from"./shelf-DjiUBfgQ.js";import{i as r,n as i}from"./plugin-Cjr7lgQH.js";var a=(e,t)=>(e??[]).reduce((e,n)=>{let r=n?.[t];return e+(Number(r&&typeof r==`object`?r.value:r)||0)},0),o=e=>e&&typeof e==`object`?e.unit??null:null,s=()=>e.string({options:`cooking`,value:({record:e})=>o(e.quantity),strict:!0}),c=(e,t)=>(e??[]).map(e=>e?.[t]==null?``:String(e[t])).filter(e=>e!==``).sort()[0]??null,l=e=>{let t=e?.value;return typeof t==`number`&&Number.isFinite(t)?t:null},u=n({shelf:`food_item`,library:`kitchen`,label:`kitchen.food_item.label`,icon:`lucide:soup`,agent:'A kitchen product is generic (buckwheat, milk), and its `variants` rows are the actual goods on the shelf. The unit is declared once on the product, inside its stock: `quantity` is written as `{"unit": "<unit>"}` — the unit alone, never a value. Every amount below it — `minQuantity`, each variant row\'s `quantity` — is written as `{"value": <number>}` alone, on that scale. Do NOT send a unit inside those amounts: the server fills it in from the product\'s `quantity.unit` and discards anything you put there. Reads hand them back as `{"value": …, "unit": …}`, which you may echo unchanged. The `value` of the product\'s `quantity`, and `expires`, are computed from the variants and MUST NOT be written — to record a purchase or a write-off, change the `quantity` of the relevant variant row, or add a variant row for a good that is not there yet. A variant with quantity 0 means "this good is known, none in stock" and is a shopping-list candidate, so do not delete it.',views:{list:[`subcategory`,`quantity`,`expires`]},fields:{name:e.title({label:`core.fields.name`}),stock:e.stats({fields:{quantity:e.measured({label:`kitchen.food_item.fields.quantity`,units:`cooking`,rules:{min:0},fields:{value:e.real({value:({record:e})=>a(e.variants,`quantity`),mutate:[`stockState`]}),unit:e.string({options:`cooking`,strict:!0,mutate:[`minQuantity.unit`,`variants.quantity.unit`]})}}),status:e.status({source:{stockState:e.string({label:`kitchen.food_item.fields.stockState`,value:({record:e})=>{let t=l(e.minQuantity);return t==null?`ok`:(l(e.quantity)??0)<t?`low`:`ok`},strict:!0,noSearch:!0,options:[{value:`ok`,title:`kitchen.food_item.options.stockState.ok`,tone:`success`},{value:`low`,title:`kitchen.food_item.options.stockState.low`,tone:`danger`}]})}}),minQuantity:e.measured({label:`kitchen.food_item.fields.minQuantity`,units:`cooking`,rules:{min:0},fields:{unit:s(),value:e.real({rules:{min:0},mutate:[`stockState`]})}}),expires:e.reminder({label:`kitchen.food_item.fields.expires`,rules:{lead:14},value:({record:e})=>c(e.variants,`expires`)})}}),hairline:e.divider({}),about:e.illustrated({label:`kitchen.food_item.fields.about`,fields:{image:e.avatar({}),text:e.text({rules:{max:1e3}})}}),photos:e.image({label:`kitchen.food_item.fields.photos`,multiple:!0}),variants:e.row({scope:`nest`,multiple:!0,label:`kitchen.food_item.fields.variants`,icon:`lucide:package`,fields:{name:e.string({label:`kitchen.food_item.variant.name`,rules:{max:200}}),quantity:e.measured({label:`kitchen.food_item.variant.quantity`,units:`cooking`,rules:{min:0},fields:{unit:s(),value:e.real({rules:{min:0},mutate:[`quantity.value`]})}}),expires:e.reminder({label:`kitchen.food_item.variant.expires`,rules:{lead:14},mutate:[`expires`]}),location:e.relation({label:`kitchen.food_item.variant.location`,options:t({library:`things`,shelf:`storage_location`})}),shops:e.link({label:`kitchen.food_item.variant.shops`,multiple:!0}),photo:e.image({label:`kitchen.food_item.variant.photo`})}}),subcategory:e.string({label:`kitchen.food_item.fields.subcategory`,rules:{max:100}}),tags:e.tags({label:`kitchen.food_item.fields.tags`}),notes:e.text({label:`kitchen.food_item.fields.notes`,rules:{max:2e3}})}}),d=async({ref:e})=>{let t=(await e?.(`product`))?.quantity;return t&&typeof t==`object`?t.unit??null:null},f=e=>{let t=e?.value;return typeof t==`number`&&Number.isFinite(t)?t:null},p=async({ref:e})=>(await e?.(`product`))?.quantity??null,m=n({shelf:`food_recipe`,library:`kitchen`,label:`kitchen.food_recipe.label`,icon:`lucide:clipboard-list`,views:{list:[`category`,`description`,`prep_time`,`cook_time`]},fields:{name:e.title({label:`core.fields.name`}),cooking:e.stats({fields:{status:e.status({source:{readiness:e.string({label:`kitchen.food_recipe.fields.readiness`,value:({record:e})=>(e.ingredients??[]).filter(e=>!e.optional).every(e=>e.stock_state===`enough`)?`ready`:`not_ready`,strict:!0,noSearch:!0,options:[{value:`ready`,title:`kitchen.food_recipe.options.readiness.ready`,tone:`success`},{value:`not_ready`,title:`kitchen.food_recipe.options.readiness.not_ready`,tone:`danger`}]})}}),servings:e.int({label:`kitchen.food_recipe.fields.servings`,rules:{min:1,max:100}}),prep_time:e.duration({label:`kitchen.food_recipe.fields.prep_time`}),cook_time:e.duration({label:`kitchen.food_recipe.fields.cook_time`})}}),hairline:e.divider({}),description:e.text({label:`kitchen.food_recipe.fields.description`,rules:{max:500}}),images:e.image({label:`kitchen.food_recipe.fields.images`,multiple:!0}),ingredients:e.row({scope:`nest`,multiple:!0,label:`kitchen.food_recipe.fields.ingredients`,icon:`lucide:carrot`,rules:{unique:[`product`]},fields:{product:e.relation({label:`kitchen.food_recipe.ingredient.product`,options:t({library:`kitchen`,shelf:`food_item`})}),amount:e.measured({label:`kitchen.food_recipe.ingredient.amount`,units:`cooking`,rules:{min:0},fields:{unit:e.string({options:`cooking`,value:d,strict:!0,cache:0}),value:e.real({rules:{min:0},mutate:[`.stock_state`]})}}),optional:e.boolean({label:`kitchen.food_recipe.ingredient.optional`,mutate:[`readiness`]}),stock:e.measured({label:`kitchen.food_recipe.ingredient.stock`,units:`cooking`,cache:0,value:p}),stock_state:e.string({label:`kitchen.food_recipe.ingredient.stock_state`,cache:0,value:async e=>{let t=f(await p(e));if(t==null)return null;let n=f(e.parent?.amount);return n==null?t>0?null:`missing`:t>=n?`enough`:t>0?`partial`:`missing`},mutate:[`readiness`],strict:!0,noSearch:!0,options:[{value:`enough`,title:`kitchen.food_recipe.options.stock_state.enough`,icon:{kind:`icon`,value:`lucide:check`},tone:`success`},{value:`partial`,title:`kitchen.food_recipe.options.stock_state.partial`,icon:{kind:`icon`,value:`lucide:minus`},tone:`danger`},{value:`missing`,title:`kitchen.food_recipe.options.stock_state.missing`,icon:{kind:`icon`,value:`lucide:x`},tone:`danger`}]})}}),ingredients_free:e.row({scope:`nest`,multiple:!0,label:`kitchen.food_recipe.fields.ingredients_free`,icon:`lucide:list`,rules:{unique:[`product`]},fields:{product:e.string({label:`kitchen.food_recipe.ingredient_free.product`,rules:{max:200}}),unit:e.unit({label:`kitchen.food_recipe.ingredient_free.unit`,options:`cooking`}),amount:e.amount({label:`kitchen.food_recipe.ingredient_free.amount`,unitFrom:`unit`,rules:{min:0}}),optional:e.boolean({label:`kitchen.food_recipe.ingredient_free.optional`})}}),prose:e.prose({label:`kitchen.food_recipe.fields.steps`,icon:`lucide:chef-hat`,fields:{steps:e.markdown({label:`kitchen.food_recipe.fields.steps_body`,rules:{max:5e3}})}}),properties:e.properties({columns:2,fields:{category:e.string({label:`kitchen.food_recipe.fields.category`,multiple:!0,strict:!0,noSearch:!0,ui:{span:6},options:[{value:`first`,title:`kitchen.food_recipe.options.category.first`},{value:`main`,title:`kitchen.food_recipe.options.category.main`},{value:`salad`,title:`kitchen.food_recipe.options.category.salad`},{value:`appetizer`,title:`kitchen.food_recipe.options.category.appetizer`},{value:`side`,title:`kitchen.food_recipe.options.category.side`},{value:`dessert`,title:`kitchen.food_recipe.options.category.dessert`},{value:`drink`,title:`kitchen.food_recipe.options.category.drink`},{value:`sauce`,title:`kitchen.food_recipe.options.category.sauce`}]}),difficulty:e.string({label:`kitchen.food_recipe.fields.difficulty`,strict:!0,noSearch:!0,ui:{span:6},options:[{value:`easy`,title:`kitchen.food_recipe.options.difficulty.easy`},{value:`medium`,title:`kitchen.food_recipe.options.difficulty.medium`},{value:`hard`,title:`kitchen.food_recipe.options.difficulty.hard`}]})}}),tags:e.tags({label:`kitchen.food_recipe.fields.tags`}),notes:e.text({label:`kitchen.food_recipe.fields.notes`,rules:{max:1e3}})}}),h=n({shelf:`preferences`,library:`kitchen`,label:`kitchen.preferences.label`,icon:`lucide:notebook-pen`,single:!0,agent:`One record. The household food habits, diets and allergies; where groceries are bought, what is bought there and in what volumes; which kitchen appliances exist and which do not. Read it before suggesting recipes, building a shopping list, or planning a menu. An appliance listed as absent is a fact, not a gap — do not propose recipes that need it.`,fields:{preferences:e.markdown({label:`kitchen.preferences.fields.preferences`,rules:{max:1e4}}),shops:e.markdown({label:`kitchen.preferences.fields.shops`,rules:{max:1e4}}),equipment:e.markdown({label:`kitchen.preferences.fields.equipment`,rules:{max:1e4}}),notes:e.text({label:`kitchen.preferences.fields.notes`,rules:{max:1e4}})}}),g=i({id:`kitchen`,version:`1.0.0`,dependsOn:[`things`],label:`kitchen.plugin.label`,description:`kitchen.plugin.description`,libraries:[{meta:r({id:`kitchen`,label:`kitchen.library.label`,icon:`lucide:cooking-pot`,agent:{description:`Food inventory and recipes — what is in stock, what is expiring, what can be cooked.`,instructions:`Read kitchen/preferences before creating, merging or renaming a product: it records how this household splits products from variants, which units each family of goods uses, and why. It governs — these rules are the mechanics, that record is the intent.`},starterHint:`what's expiring soon, or what can be cooked from what's in stock`}),shelves:[u,m,h]}],fieldContribs:[{library:`things`,shelf:`item`,field:`type`,options:[{value:`kitchenware`,title:`kitchen.contrib.type.kitchenware`}]}]});export{g as default};